mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
nghttp2-based HTTP layer in netmgr
This commit includes work-in-progress implementation of DNS-over-HTTP(S). Server-side code remains mostly untested, and there is only support for POST requests.
This commit is contained in:
parent
cdf9d21731
commit
7a96081360
19 changed files with 2061 additions and 27 deletions
|
|
@ -285,6 +285,7 @@ stages:
|
|||
"with-openssl=C:/OpenSSL"
|
||||
"with-libxml2=C:/libxml2"
|
||||
"with-libuv=C:/libuv"
|
||||
"with-nghttp2=C:/nghttp2"
|
||||
"without-python"
|
||||
"with-system-tests"
|
||||
x64'
|
||||
|
|
|
|||
22
COPYRIGHT
22
COPYRIGHT
|
|
@ -367,3 +367,25 @@ distributed under the License is distributed on an "AS IS" BASIS,
|
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
|
|
|
|||
|
|
@ -138,7 +138,8 @@ const FileData installFiles[] =
|
|||
{"libdns.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
|
||||
{"libirs.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
|
||||
{"libeay32.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
|
||||
{"libuv.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
|
||||
{"nghttp2.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
|
||||
{"uv.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
|
||||
#ifdef HAVE_LIBXML2
|
||||
{"libxml2.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
|
||||
#endif
|
||||
|
|
|
|||
11
configure.ac
11
configure.ac
|
|
@ -124,7 +124,7 @@ AS_IF([test "$enable_static" != "no" && test "$enable_developer" != "yes"],
|
|||
#
|
||||
# Set the default CFLAGS and CPPFLAGS
|
||||
#
|
||||
STD_CFLAGS="-Wall -Wextra -Wwrite-strings -Wcast-qual -Wpointer-arith -Wno-missing-field-initializers -Wformat -Wshadow"
|
||||
STD_CFLAGS="-Wall -Wextra -Wwrite-strings -Wpointer-arith -Wno-missing-field-initializers -Wformat -Wshadow"
|
||||
|
||||
# These should be always errors
|
||||
STD_CFLAGS="$STD_CFLAGS -Werror=implicit-function-declaration -Werror=missing-prototypes -Werror=format-security -Werror=parentheses -Werror=implicit -Werror=strict-prototypes"
|
||||
|
|
@ -574,6 +574,15 @@ LIBS="$LIBS $LIBUV_LIBS"
|
|||
AC_CHECK_FUNCS([uv_handle_get_data uv_handle_set_data uv_import uv_udp_connect uv_translate_sys_error])
|
||||
AX_RESTORE_FLAGS([libuv])
|
||||
|
||||
# libnghttp2
|
||||
AC_MSG_CHECKING([for libnghttp2])
|
||||
PKG_CHECK_MODULES([LIBNGHTTP2], [libnghttp2 >= 1.6.0], [],
|
||||
[AC_MSG_ERROR([libnghttp2 not found])])
|
||||
AX_SAVE_FLAGS([libnghttp2])
|
||||
|
||||
CFLAGS="$CFLAGS $LIBNGHTTP2_CFLAGS"
|
||||
LIBS="$LIBS $LIBNGHTTP2_LIBS"
|
||||
|
||||
#
|
||||
# flockfile is usually provided by pthreads
|
||||
#
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ libisc_la_HEADERS = \
|
|||
include/isc/tls.h \
|
||||
include/isc/tm.h \
|
||||
include/isc/types.h \
|
||||
include/isc/url.h \
|
||||
include/isc/utf8.h \
|
||||
include/isc/util.h \
|
||||
pthreads/include/isc/condition.h\
|
||||
|
|
@ -124,6 +125,7 @@ libisc_la_SOURCES = \
|
|||
$(libisc_la_HEADERS) \
|
||||
$(pk11_HEADERS) \
|
||||
$(pkcs11_HEADERS) \
|
||||
netmgr/http.c \
|
||||
netmgr/netmgr-int.h \
|
||||
netmgr/netmgr.c \
|
||||
netmgr/tcp.c \
|
||||
|
|
@ -150,6 +152,7 @@ libisc_la_SOURCES = \
|
|||
unix/stdtime.c \
|
||||
unix/syslog.c \
|
||||
unix/time.c \
|
||||
url.c \
|
||||
pk11.c \
|
||||
pk11_result.c \
|
||||
aes.c \
|
||||
|
|
|
|||
|
|
@ -505,3 +505,42 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
|
|||
* The connected socket can only be accessed via the handle passed to
|
||||
* 'cb'.
|
||||
*/
|
||||
|
||||
typedef void (*isc_nm_http_cb_t)(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
isc_region_t *postdata, isc_region_t *getdata,
|
||||
void *cbarg);
|
||||
/*%<
|
||||
* Callback function to be used when receiving an HTTP request.
|
||||
*
|
||||
* 'handle' the handle that can be used to send back the answer.
|
||||
* 'eresult' the result of the event.
|
||||
* 'postdata' contains the received POST data, if any. It will be freed
|
||||
* after return by caller.
|
||||
* 'getdata' contains the received GET data (past '?'), if any. It will be
|
||||
* freed after return by caller.
|
||||
* 'cbarg' the callback argument passed to listen function.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_nm_doh_request(isc_nm_t *mgr, const char *uri, isc_region_t *message,
|
||||
isc_nm_recv_cb_t cb, void *cbarg, isc_ssl_ctx_t *ctx);
|
||||
|
||||
isc_result_t
|
||||
isc_nm_httpsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
|
||||
const char *uri, isc_nm_cb_t cb, void *cbarg,
|
||||
unsigned int timeout, size_t extrahandlesize);
|
||||
|
||||
isc_result_t
|
||||
isc_nm_listenhttps(isc_nm_t *mgr, isc_nmiface_t *iface, int backlog,
|
||||
isc_quota_t *quota, isc_ssl_ctx_t *ctx,
|
||||
isc_nmsocket_t **sockp);
|
||||
|
||||
isc_result_t
|
||||
isc_nm_http_add_endpoint(isc_nmsocket_t *sock, const char *uri,
|
||||
isc_nm_http_cb_t cb, void *cbarg,
|
||||
size_t extrahandlesize);
|
||||
|
||||
isc_result_t
|
||||
isc_nm_http_add_doh_endpoint(isc_nmsocket_t *sock, const char *uri,
|
||||
isc_nm_recv_cb_t cb, void *cbarg,
|
||||
size_t extrahandlesize);
|
||||
|
|
|
|||
80
lib/isc/include/isc/url.h
Normal file
80
lib/isc/include/isc/url.h
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <isc/result.h>
|
||||
|
||||
/*
|
||||
* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run
|
||||
* faster
|
||||
*/
|
||||
#ifndef HTTP_PARSER_STRICT
|
||||
#define HTTP_PARSER_STRICT 1
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
ISC_UF_SCHEMA = 0,
|
||||
ISC_UF_HOST = 1,
|
||||
ISC_UF_PORT = 2,
|
||||
ISC_UF_PATH = 3,
|
||||
ISC_UF_QUERY = 4,
|
||||
ISC_UF_FRAGMENT = 5,
|
||||
ISC_UF_USERINFO = 6,
|
||||
ISC_UF_MAX = 7
|
||||
} isc_url_field_t;
|
||||
|
||||
/* Result structure for isc_url_parse().
|
||||
*
|
||||
* Callers should index into field_data[] with UF_* values iff field_set
|
||||
* has the relevant (1 << UF_*) bit set. As a courtesy to clients (and
|
||||
* because we probably have padding left over), we convert any port to
|
||||
* a uint16_t.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t field_set; /* Bitmask of (1 << UF_*) values */
|
||||
uint16_t port; /* Converted UF_PORT string */
|
||||
|
||||
struct {
|
||||
uint16_t off; /* Offset into buffer in which field starts */
|
||||
uint16_t len; /* Length of run in buffer */
|
||||
} field_data[ISC_UF_MAX];
|
||||
} isc_url_parser_t;
|
||||
|
||||
isc_result_t
|
||||
isc_url_parse(const char *buf, size_t buflen, bool is_connect,
|
||||
isc_url_parser_t *up);
|
||||
/*%<
|
||||
* Parse a URL; return nonzero on failure
|
||||
*/
|
||||
1077
lib/isc/netmgr/http.c
Normal file
1077
lib/isc/netmgr/http.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -155,6 +155,8 @@ isc__nm_dump_active(isc_nm_t *nm);
|
|||
#define isc__nmsocket_prep_destroy(sock) isc___nmsocket_prep_destroy(sock)
|
||||
#endif
|
||||
|
||||
typedef struct isc_nm_http2_session isc_nm_http2_session_t;
|
||||
|
||||
/*
|
||||
* Single network event loop worker.
|
||||
*/
|
||||
|
|
@ -207,6 +209,8 @@ struct isc_nmhandle {
|
|||
isc_nmsocket_t *sock;
|
||||
size_t ah_pos; /* Position in the socket's 'active handles' array */
|
||||
|
||||
isc_nm_http2_session_t *httpsession;
|
||||
|
||||
isc_sockaddr_t peer;
|
||||
isc_sockaddr_t local;
|
||||
isc_nm_opaquecb_t doreset; /* reset extra callback, external */
|
||||
|
|
@ -293,11 +297,22 @@ typedef enum isc__netievent_type {
|
|||
|
||||
typedef union {
|
||||
isc_nm_recv_cb_t recv;
|
||||
isc_nm_http_cb_t http;
|
||||
isc_nm_cb_t send;
|
||||
isc_nm_cb_t connect;
|
||||
isc_nm_accept_cb_t accept;
|
||||
} isc__nm_cb_t;
|
||||
|
||||
typedef struct isc_nm_http2_server_handler isc_nm_http2_server_handler_t;
|
||||
|
||||
struct isc_nm_http2_server_handler {
|
||||
char *path;
|
||||
isc_nm_http_cb_t cb;
|
||||
void *cbarg;
|
||||
size_t extrahandlesize;
|
||||
LINK(isc_nm_http2_server_handler_t) link;
|
||||
};
|
||||
|
||||
/*
|
||||
* Wrapper around uv_req_t with 'our' fields in it. req->data should
|
||||
* always point to its parent. Note that we always allocate more than
|
||||
|
|
@ -652,7 +667,9 @@ typedef enum isc_nmsocket_type {
|
|||
isc_nm_tlslistener,
|
||||
isc_nm_tlssocket,
|
||||
isc_nm_tlsdnslistener,
|
||||
isc_nm_tlsdnssocket
|
||||
isc_nm_tlsdnssocket,
|
||||
isc_nm_httplistener,
|
||||
isc_nm_httpstream
|
||||
} isc_nmsocket_type;
|
||||
|
||||
/*%
|
||||
|
|
@ -684,12 +701,26 @@ typedef struct isc_nmsocket_tls_send_req {
|
|||
isc_region_t data;
|
||||
} isc_nmsocket_tls_send_req_t;
|
||||
|
||||
typedef struct isc_nmsocket_h2 {
|
||||
isc_nmsocket_t *psock; /* owner of the structure */
|
||||
char *request_path;
|
||||
char *query_data;
|
||||
isc_nm_http2_server_handler_t *handler;
|
||||
|
||||
uint8_t buf[65535];
|
||||
size_t bufsize;
|
||||
size_t bufpos;
|
||||
|
||||
int32_t stream_id;
|
||||
LINK(struct isc_nmsocket_h2) link;
|
||||
} isc_nmsocket_h2_t;
|
||||
struct isc_nmsocket {
|
||||
/*% Unlocked, RO */
|
||||
int magic;
|
||||
int tid;
|
||||
isc_nmsocket_type type;
|
||||
isc_nm_t *mgr;
|
||||
|
||||
/*% Parent socket for multithreaded listeners */
|
||||
isc_nmsocket_t *parent;
|
||||
/*% Listener socket this connection was accepted on */
|
||||
|
|
@ -740,6 +771,7 @@ struct isc_nmsocket {
|
|||
ISC_LIST(isc__nm_uvreq_t) sends;
|
||||
} tlsstream;
|
||||
|
||||
isc_nmsocket_h2_t h2;
|
||||
/*%
|
||||
* quota is the TCP client, attached when a TCP connection
|
||||
* is established. pquota is a non-attached pointer to the
|
||||
|
|
@ -941,6 +973,9 @@ struct isc_nmsocket {
|
|||
void *accept_cbarg;
|
||||
|
||||
atomic_int_fast32_t active_child_connections;
|
||||
|
||||
ISC_LIST(isc_nm_http2_server_handler_t) handlers;
|
||||
|
||||
#ifdef NETMGR_TRACE
|
||||
void *backtrace[TRACE_SIZE];
|
||||
int backtrace_size;
|
||||
|
|
@ -1105,8 +1140,8 @@ isc__nm_async_shutdown(isc__networker_t *worker, isc__netievent_t *ev0);
|
|||
*/
|
||||
|
||||
void
|
||||
isc__nm_udp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
|
||||
void *cbarg);
|
||||
isc__nm_udp_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
||||
isc_nm_cb_t cb, void *cbarg);
|
||||
/*%<
|
||||
* Back-end implementation of isc_nm_send() for UDP handles.
|
||||
*/
|
||||
|
|
@ -1167,8 +1202,8 @@ isc__nm_async_udpclose(isc__networker_t *worker, isc__netievent_t *ev0);
|
|||
*/
|
||||
|
||||
void
|
||||
isc__nm_tcp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
|
||||
void *cbarg);
|
||||
isc__nm_tcp_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
||||
isc_nm_cb_t cb, void *cbarg);
|
||||
/*%<
|
||||
* Back-end implementation of isc_nm_send() for TCP handles.
|
||||
*/
|
||||
|
|
@ -1349,6 +1384,10 @@ void
|
|||
isc__nm_tlsdns_send(isc_nmhandle_t *handle, isc_region_t *region,
|
||||
isc_nm_cb_t cb, void *cbarg);
|
||||
|
||||
void
|
||||
isc__nm_tls_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
||||
isc_nm_cb_t cb, void *cbarg);
|
||||
|
||||
void
|
||||
isc__nm_tls_cancelread(isc_nmhandle_t *handle);
|
||||
|
||||
|
|
@ -1405,10 +1444,6 @@ isc__nm_tlsdns_cancelread(isc_nmhandle_t *handle);
|
|||
* Stop reading on a connected TLSDNS handle.
|
||||
*/
|
||||
|
||||
void
|
||||
isc__nm_tls_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
|
||||
void *cbarg);
|
||||
|
||||
void
|
||||
isc__nm_tls_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg);
|
||||
|
||||
|
|
@ -1437,6 +1472,10 @@ isc__nm_tls_cleanup_data(isc_nmsocket_t *sock);
|
|||
void
|
||||
isc__nm_tls_stoplistening(isc_nmsocket_t *sock);
|
||||
|
||||
void
|
||||
isc__nm_http_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
||||
isc_nm_cb_t cb, void *cbarg);
|
||||
|
||||
#define isc__nm_uverr2result(x) \
|
||||
isc___nm_uverr2result(x, true, __FILE__, __LINE__, __func__)
|
||||
isc_result_t
|
||||
|
|
|
|||
|
|
@ -1696,6 +1696,9 @@ isc_nm_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
|
|||
case isc_nm_tlsdnssocket:
|
||||
isc__nm_tlsdns_send(handle, region, cb, cbarg);
|
||||
break;
|
||||
case isc_nm_httpstream:
|
||||
isc__nm_http_send(handle, region, cb, cbarg);
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
|
|
|
|||
|
|
@ -1155,8 +1155,8 @@ failure:
|
|||
}
|
||||
|
||||
void
|
||||
isc__nm_tcp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
|
||||
void *cbarg) {
|
||||
isc__nm_tcp_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
||||
isc_nm_cb_t cb, void *cbarg) {
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||
|
||||
|
|
|
|||
|
|
@ -559,11 +559,12 @@ isc__nm_async_tlssend(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||
}
|
||||
|
||||
void
|
||||
isc__nm_tls_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
|
||||
void *cbarg) {
|
||||
isc__nm_tls_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
||||
isc_nm_cb_t cb, void *cbarg) {
|
||||
isc__netievent_tlssend_t *ievent = NULL;
|
||||
isc__nm_uvreq_t *uvreq = NULL;
|
||||
isc_nmsocket_t *sock = NULL;
|
||||
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||
|
||||
|
|
@ -875,7 +876,6 @@ isc__nm_async_tlsconnect(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||
if (result != ISC_R_SUCCESS) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return;
|
||||
error:
|
||||
tlshandle = isc__nmhandle_get(tlssock, NULL, NULL);
|
||||
|
|
|
|||
|
|
@ -478,8 +478,8 @@ free:
|
|||
* another thread.
|
||||
*/
|
||||
void
|
||||
isc__nm_udp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
|
||||
void *cbarg) {
|
||||
isc__nm_udp_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
||||
isc_nm_cb_t cb, void *cbarg) {
|
||||
isc_nmsocket_t *sock = handle->sock;
|
||||
isc_nmsocket_t *psock = NULL, *rsock = sock;
|
||||
isc_sockaddr_t *peer = &handle->peer;
|
||||
|
|
|
|||
667
lib/isc/url.c
Normal file
667
lib/isc/url.c
Normal file
|
|
@ -0,0 +1,667 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/url.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#ifndef BIT_AT
|
||||
#define BIT_AT(a, i) \
|
||||
(!!((unsigned int)(a)[(unsigned int)(i) >> 3] & \
|
||||
(1 << ((unsigned int)(i)&7))))
|
||||
#endif
|
||||
|
||||
#if HTTP_PARSER_STRICT
|
||||
#define T(v) 0
|
||||
#else
|
||||
#define T(v) v
|
||||
#endif
|
||||
|
||||
static const uint8_t normal_url_char[32] = {
|
||||
/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
|
||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
|
||||
/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
|
||||
0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0,
|
||||
/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
|
||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
|
||||
/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
|
||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
|
||||
/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
|
||||
0 | 2 | 4 | 0 | 16 | 32 | 64 | 128,
|
||||
/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 0,
|
||||
/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 0,
|
||||
};
|
||||
|
||||
#undef T
|
||||
|
||||
typedef enum {
|
||||
s_dead = 1, /* important that this is > 0 */
|
||||
|
||||
s_start_req_or_res,
|
||||
s_res_or_resp_H,
|
||||
s_start_res,
|
||||
s_res_H,
|
||||
s_res_HT,
|
||||
s_res_HTT,
|
||||
s_res_HTTP,
|
||||
s_res_http_major,
|
||||
s_res_http_dot,
|
||||
s_res_http_minor,
|
||||
s_res_http_end,
|
||||
s_res_first_status_code,
|
||||
s_res_status_code,
|
||||
s_res_status_start,
|
||||
s_res_status,
|
||||
s_res_line_almost_done,
|
||||
|
||||
s_start_req,
|
||||
|
||||
s_req_method,
|
||||
s_req_spaces_before_url,
|
||||
s_req_schema,
|
||||
s_req_schema_slash,
|
||||
s_req_schema_slash_slash,
|
||||
s_req_server_start,
|
||||
s_req_server,
|
||||
s_req_server_with_at,
|
||||
s_req_path,
|
||||
s_req_query_string_start,
|
||||
s_req_query_string,
|
||||
s_req_fragment_start,
|
||||
s_req_fragment,
|
||||
s_req_http_start,
|
||||
s_req_http_H,
|
||||
s_req_http_HT,
|
||||
s_req_http_HTT,
|
||||
s_req_http_HTTP,
|
||||
s_req_http_I,
|
||||
s_req_http_IC,
|
||||
s_req_http_major,
|
||||
s_req_http_dot,
|
||||
s_req_http_minor,
|
||||
s_req_http_end,
|
||||
s_req_line_almost_done,
|
||||
|
||||
s_header_field_start,
|
||||
s_header_field,
|
||||
s_header_value_discard_ws,
|
||||
s_header_value_discard_ws_almost_done,
|
||||
s_header_value_discard_lws,
|
||||
s_header_value_start,
|
||||
s_header_value,
|
||||
s_header_value_lws,
|
||||
|
||||
s_header_almost_done,
|
||||
|
||||
s_chunk_size_start,
|
||||
s_chunk_size,
|
||||
s_chunk_parameters,
|
||||
s_chunk_size_almost_done,
|
||||
|
||||
s_headers_almost_done,
|
||||
s_headers_done,
|
||||
|
||||
/*
|
||||
* Important: 's_headers_done' must be the last 'header' state. All
|
||||
* states beyond this must be 'body' states. It is used for overflow
|
||||
* checking. See the PARSING_HEADER() macro.
|
||||
*/
|
||||
|
||||
s_chunk_data,
|
||||
s_chunk_data_almost_done,
|
||||
s_chunk_data_done,
|
||||
|
||||
s_body_identity,
|
||||
s_body_identity_eof,
|
||||
|
||||
s_message_done
|
||||
} state_t;
|
||||
|
||||
typedef enum {
|
||||
s_http_host_dead = 1,
|
||||
s_http_userinfo_start,
|
||||
s_http_userinfo,
|
||||
s_http_host_start,
|
||||
s_http_host_v6_start,
|
||||
s_http_host,
|
||||
s_http_host_v6,
|
||||
s_http_host_v6_end,
|
||||
s_http_host_v6_zone_start,
|
||||
s_http_host_v6_zone,
|
||||
s_http_host_port_start,
|
||||
s_http_host_port
|
||||
} host_state_t;
|
||||
|
||||
/* Macros for character classes; depends on strict-mode */
|
||||
#define IS_MARK(c) \
|
||||
((c) == '-' || (c) == '_' || (c) == '.' || (c) == '!' || (c) == '~' || \
|
||||
(c) == '*' || (c) == '\'' || (c) == '(' || (c) == ')')
|
||||
#define IS_USERINFO_CHAR(c) \
|
||||
(isalnum(c) || IS_MARK(c) || (c) == '%' || (c) == ';' || (c) == ':' || \
|
||||
(c) == '&' || (c) == '=' || (c) == '+' || (c) == '$' || (c) == ',')
|
||||
|
||||
#if HTTP_PARSER_STRICT
|
||||
#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c))
|
||||
#define IS_HOST_CHAR(c) (isalnum(c) || (c) == '.' || (c) == '-')
|
||||
#else
|
||||
#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c) || ((c)&0x80))
|
||||
#define IS_HOST_CHAR(c) (isalnum(c) || (c) == '.' || (c) == '-' || (c) == '_')
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Our URL parser.
|
||||
*
|
||||
* This is designed to be shared by http_parser_execute() for URL validation,
|
||||
* hence it has a state transition + byte-for-byte interface. In addition, it
|
||||
* is meant to be embedded in http_parser_parse_url(), which does the dirty
|
||||
* work of turning state transitions URL components for its API.
|
||||
*
|
||||
* This function should only be invoked with non-space characters. It is
|
||||
* assumed that the caller cares about (and can detect) the transition between
|
||||
* URL and non-URL states by looking for these.
|
||||
*/
|
||||
static state_t
|
||||
parse_url_char(state_t s, const char ch) {
|
||||
if (ch == ' ' || ch == '\r' || ch == '\n') {
|
||||
return (s_dead);
|
||||
}
|
||||
|
||||
#if HTTP_PARSER_STRICT
|
||||
if (ch == '\t' || ch == '\f') {
|
||||
return (s_dead);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (s) {
|
||||
case s_req_spaces_before_url:
|
||||
/* Proxied requests are followed by scheme of an absolute URI
|
||||
* (alpha). All methods except CONNECT are followed by '/' or
|
||||
* '*'.
|
||||
*/
|
||||
|
||||
if (ch == '/' || ch == '*') {
|
||||
return (s_req_path);
|
||||
}
|
||||
|
||||
if (isalpha(ch)) {
|
||||
return (s_req_schema);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_schema:
|
||||
if (isalpha(ch)) {
|
||||
return (s);
|
||||
}
|
||||
|
||||
if (ch == ':') {
|
||||
return (s_req_schema_slash);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_schema_slash:
|
||||
if (ch == '/') {
|
||||
return (s_req_schema_slash_slash);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_schema_slash_slash:
|
||||
if (ch == '/') {
|
||||
return (s_req_server_start);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_server_with_at:
|
||||
if (ch == '@') {
|
||||
return (s_dead);
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case s_req_server_start:
|
||||
case s_req_server:
|
||||
if (ch == '/') {
|
||||
return (s_req_path);
|
||||
}
|
||||
|
||||
if (ch == '?') {
|
||||
return (s_req_query_string_start);
|
||||
}
|
||||
|
||||
if (ch == '@') {
|
||||
return (s_req_server_with_at);
|
||||
}
|
||||
|
||||
if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') {
|
||||
return (s_req_server);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_path:
|
||||
if (IS_URL_CHAR(ch)) {
|
||||
return (s);
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case '?':
|
||||
return (s_req_query_string_start);
|
||||
|
||||
case '#':
|
||||
return (s_req_fragment_start);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_query_string_start:
|
||||
case s_req_query_string:
|
||||
if (IS_URL_CHAR(ch)) {
|
||||
return (s_req_query_string);
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case '?':
|
||||
/* allow extra '?' in query string */
|
||||
return (s_req_query_string);
|
||||
|
||||
case '#':
|
||||
return (s_req_fragment_start);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_fragment_start:
|
||||
if (IS_URL_CHAR(ch)) {
|
||||
return (s_req_fragment);
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case '?':
|
||||
return (s_req_fragment);
|
||||
|
||||
case '#':
|
||||
return (s);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_fragment:
|
||||
if (IS_URL_CHAR(ch)) {
|
||||
return (s);
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case '?':
|
||||
case '#':
|
||||
return (s);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We should never fall out of the switch above unless there's an
|
||||
* error.
|
||||
*/
|
||||
return (s_dead);
|
||||
}
|
||||
|
||||
static host_state_t
|
||||
http_parse_host_char(host_state_t s, const char ch) {
|
||||
switch (s) {
|
||||
case s_http_userinfo:
|
||||
case s_http_userinfo_start:
|
||||
if (ch == '@') {
|
||||
return (s_http_host_start);
|
||||
}
|
||||
|
||||
if (IS_USERINFO_CHAR(ch)) {
|
||||
return (s_http_userinfo);
|
||||
}
|
||||
break;
|
||||
|
||||
case s_http_host_start:
|
||||
if (ch == '[') {
|
||||
return (s_http_host_v6_start);
|
||||
}
|
||||
|
||||
if (IS_HOST_CHAR(ch)) {
|
||||
return (s_http_host);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_http_host:
|
||||
if (IS_HOST_CHAR(ch)) {
|
||||
return (s_http_host);
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case s_http_host_v6_end:
|
||||
if (ch == ':') {
|
||||
return (s_http_host_port_start);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_http_host_v6:
|
||||
if (ch == ']') {
|
||||
return (s_http_host_v6_end);
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case s_http_host_v6_start:
|
||||
if (isxdigit(ch) || ch == ':' || ch == '.') {
|
||||
return (s_http_host_v6);
|
||||
}
|
||||
|
||||
if (s == s_http_host_v6 && ch == '%') {
|
||||
return (s_http_host_v6_zone_start);
|
||||
}
|
||||
break;
|
||||
|
||||
case s_http_host_v6_zone:
|
||||
if (ch == ']') {
|
||||
return (s_http_host_v6_end);
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case s_http_host_v6_zone_start:
|
||||
/* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */
|
||||
if (isalnum(ch) || ch == '%' || ch == '.' || ch == '-' ||
|
||||
ch == '_' || ch == '~')
|
||||
{
|
||||
return (s_http_host_v6_zone);
|
||||
}
|
||||
break;
|
||||
|
||||
case s_http_host_port:
|
||||
case s_http_host_port_start:
|
||||
if (isdigit(ch)) {
|
||||
return (s_http_host_port);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (s_http_host_dead);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
http_parse_host(const char *buf, isc_url_parser_t *up, int found_at) {
|
||||
host_state_t s;
|
||||
const char *p = NULL;
|
||||
size_t buflen = up->field_data[ISC_UF_HOST].off +
|
||||
up->field_data[ISC_UF_HOST].len;
|
||||
|
||||
REQUIRE((up->field_set & (1 << ISC_UF_HOST)) != 0);
|
||||
|
||||
up->field_data[ISC_UF_HOST].len = 0;
|
||||
|
||||
s = found_at ? s_http_userinfo_start : s_http_host_start;
|
||||
|
||||
for (p = buf + up->field_data[ISC_UF_HOST].off; p < buf + buflen; p++) {
|
||||
host_state_t new_s = http_parse_host_char(s, *p);
|
||||
|
||||
if (new_s == s_http_host_dead) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
switch (new_s) {
|
||||
case s_http_host:
|
||||
if (s != s_http_host) {
|
||||
up->field_data[ISC_UF_HOST].off =
|
||||
(uint16_t)(p - buf);
|
||||
}
|
||||
up->field_data[ISC_UF_HOST].len++;
|
||||
break;
|
||||
|
||||
case s_http_host_v6:
|
||||
if (s != s_http_host_v6) {
|
||||
up->field_data[ISC_UF_HOST].off =
|
||||
(uint16_t)(p - buf);
|
||||
}
|
||||
up->field_data[ISC_UF_HOST].len++;
|
||||
break;
|
||||
|
||||
case s_http_host_v6_zone_start:
|
||||
case s_http_host_v6_zone:
|
||||
up->field_data[ISC_UF_HOST].len++;
|
||||
break;
|
||||
|
||||
case s_http_host_port:
|
||||
if (s != s_http_host_port) {
|
||||
up->field_data[ISC_UF_PORT].off =
|
||||
(uint16_t)(p - buf);
|
||||
up->field_data[ISC_UF_PORT].len = 0;
|
||||
up->field_set |= (1 << ISC_UF_PORT);
|
||||
}
|
||||
up->field_data[ISC_UF_PORT].len++;
|
||||
break;
|
||||
|
||||
case s_http_userinfo:
|
||||
if (s != s_http_userinfo) {
|
||||
up->field_data[ISC_UF_USERINFO].off =
|
||||
(uint16_t)(p - buf);
|
||||
up->field_data[ISC_UF_USERINFO].len = 0;
|
||||
up->field_set |= (1 << ISC_UF_USERINFO);
|
||||
}
|
||||
up->field_data[ISC_UF_USERINFO].len++;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
s = new_s;
|
||||
}
|
||||
|
||||
/* Make sure we don't end somewhere unexpected */
|
||||
switch (s) {
|
||||
case s_http_host_start:
|
||||
case s_http_host_v6_start:
|
||||
case s_http_host_v6:
|
||||
case s_http_host_v6_zone_start:
|
||||
case s_http_host_v6_zone:
|
||||
case s_http_host_port_start:
|
||||
case s_http_userinfo:
|
||||
case s_http_userinfo_start:
|
||||
return (ISC_R_FAILURE);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_url_parse(const char *buf, size_t buflen, bool is_connect,
|
||||
isc_url_parser_t *up) {
|
||||
state_t s;
|
||||
isc_url_field_t uf, old_uf;
|
||||
int found_at = 0;
|
||||
const char *p = NULL;
|
||||
|
||||
if (buflen == 0) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
up->port = up->field_set = 0;
|
||||
s = is_connect ? s_req_server_start : s_req_spaces_before_url;
|
||||
old_uf = ISC_UF_MAX;
|
||||
|
||||
for (p = buf; p < buf + buflen; p++) {
|
||||
s = parse_url_char(s, *p);
|
||||
|
||||
/* Figure out the next field that we're operating on */
|
||||
switch (s) {
|
||||
case s_dead:
|
||||
return (ISC_R_FAILURE);
|
||||
|
||||
/* Skip delimiters */
|
||||
case s_req_schema_slash:
|
||||
case s_req_schema_slash_slash:
|
||||
case s_req_server_start:
|
||||
case s_req_query_string_start:
|
||||
case s_req_fragment_start:
|
||||
continue;
|
||||
|
||||
case s_req_schema:
|
||||
uf = ISC_UF_SCHEMA;
|
||||
break;
|
||||
|
||||
case s_req_server_with_at:
|
||||
found_at = 1;
|
||||
/* FALLTHROUGH */
|
||||
case s_req_server:
|
||||
uf = ISC_UF_HOST;
|
||||
break;
|
||||
|
||||
case s_req_path:
|
||||
uf = ISC_UF_PATH;
|
||||
break;
|
||||
|
||||
case s_req_query_string:
|
||||
uf = ISC_UF_QUERY;
|
||||
break;
|
||||
|
||||
case s_req_fragment:
|
||||
uf = ISC_UF_FRAGMENT;
|
||||
break;
|
||||
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
}
|
||||
|
||||
/* Nothing's changed; soldier on */
|
||||
if (uf == old_uf) {
|
||||
up->field_data[uf].len++;
|
||||
continue;
|
||||
}
|
||||
|
||||
up->field_data[uf].off = (uint16_t)(p - buf);
|
||||
up->field_data[uf].len = 1;
|
||||
|
||||
up->field_set |= (1 << uf);
|
||||
old_uf = uf;
|
||||
}
|
||||
|
||||
/* host must be present if there is a schema */
|
||||
/* parsing http:///toto will fail */
|
||||
if ((up->field_set & (1 << ISC_UF_SCHEMA)) &&
|
||||
(up->field_set & (1 << ISC_UF_HOST)) == 0)
|
||||
{
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
if (up->field_set & (1 << ISC_UF_HOST)) {
|
||||
isc_result_t result;
|
||||
|
||||
result = http_parse_host(buf, up, found_at);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
|
||||
/* CONNECT requests can only contain "hostname:port" */
|
||||
if (is_connect &&
|
||||
up->field_set != ((1 << ISC_UF_HOST) | (1 << ISC_UF_PORT))) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
if (up->field_set & (1 << ISC_UF_PORT)) {
|
||||
uint16_t off;
|
||||
uint16_t len;
|
||||
const char *pp = NULL;
|
||||
const char *end = NULL;
|
||||
unsigned long v;
|
||||
|
||||
off = up->field_data[ISC_UF_PORT].off;
|
||||
len = up->field_data[ISC_UF_PORT].len;
|
||||
end = buf + off + len;
|
||||
|
||||
/*
|
||||
* NOTE: The characters are already validated and are in the
|
||||
* [0-9] range
|
||||
*/
|
||||
INSIST(off + len <= buflen);
|
||||
|
||||
v = 0;
|
||||
for (pp = buf + off; pp < end; p++) {
|
||||
v *= 10;
|
||||
v += *pp - '0';
|
||||
|
||||
/* Ports have a max value of 2^16 */
|
||||
if (v > 0xffff) {
|
||||
return (ISC_R_RANGE);
|
||||
}
|
||||
}
|
||||
|
||||
up->port = (uint16_t)v;
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
|
@ -448,6 +448,7 @@ isc_nm_cancelread
|
|||
isc_nm_closedown
|
||||
isc_nm_destroy
|
||||
isc_nm_detach
|
||||
isc_nm_listenhttps
|
||||
isc_nm_listentcpdns
|
||||
isc_nm_listentls
|
||||
isc_nm_listentlsdns
|
||||
|
|
@ -708,6 +709,7 @@ isc_tlsctx_createserver
|
|||
isc_tlsctx_free
|
||||
isc_tm_timegm
|
||||
isc_tm_strptime
|
||||
isc_url_parse
|
||||
isc_utf8_bom
|
||||
isc_utf8_valid
|
||||
isc_win32os_versioncheck
|
||||
|
|
|
|||
|
|
@ -260,6 +260,9 @@
|
|||
<ClInclude Include="..\include\isc\types.h">
|
||||
<Filter>Library Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\isc\url.h">
|
||||
<Filter>Library Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\isc\utf8.h">
|
||||
<Filter>Library Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -614,6 +617,9 @@
|
|||
<ClCompile Include="..\tm.c">
|
||||
<Filter>Library Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\url.c">
|
||||
<Filter>Library Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\utf8.c">
|
||||
<Filter>Library Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -62,11 +62,11 @@
|
|||
@IF PKCS11
|
||||
<PreprocessorDefinitions>BIND9;@PK11_LIB_LOCATION@WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBISC_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@LIBUV_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;..\;win32;..\..\isccfg\include;..\..\dns\win32\include;..\..\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@LIBUV_INC@@NGHTTP2_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;..\;win32;..\..\isccfg\include;..\..\dns\win32\include;..\..\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
@ELSE PKCS11
|
||||
<PreprocessorDefinitions>BIND9;WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBISC_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@LIBUV_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;..\;win32;..\..\isccfg\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@LIBUV_INC@@NGHTTP2_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;..\;win32;..\..\isccfg\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
@END PKCS11
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
|
||||
|
|
@ -80,7 +80,7 @@
|
|||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
|
||||
<AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@@LIBUV_LIB@@LIBXML2_LIB@@ZLIB_LIB@ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@@LIBUV_LIB@@NGHTTP2_LIB@@LIBXML2_LIB@@ZLIB_LIB@ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>$(ProjectName).def</ModuleDefinitionFile>
|
||||
<ImportLibrary>.\$(Configuration)\$(ProjectName).lib</ImportLibrary>
|
||||
</Link>
|
||||
|
|
@ -116,6 +116,9 @@ echo Copying the libxml DLL.
|
|||
copy @LIBXML2_DLL@ ..\Build\Debug\
|
||||
@END LIBXML2
|
||||
|
||||
echo Copying nghttp2 DLL.
|
||||
copy @NGHTTP2_DLL@ ..\Build\Debug\
|
||||
|
||||
@IF GSSAPI
|
||||
echo Copying the GSSAPI and KRB5 DLLs.
|
||||
|
||||
|
|
@ -163,11 +166,11 @@ copy InstallFiles ..\Build\Debug\
|
|||
@IF PKCS11
|
||||
<PreprocessorDefinitions>BIND9;@PK11_LIB_LOCATION@WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBISC_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@LIBUV_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;..\;win32;..\..\isccfg\include;..\..\dns\win32\include;..\..\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@LIBUV_INC@@NGHTTP2_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;..\;win32;..\..\isccfg\include;..\..\dns\win32\include;..\..\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
@ELSE PKCS11
|
||||
<PreprocessorDefinitions>BIND9;WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBISC_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@LIBUV_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;..\;win32;..\..\isccfg\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@LIBUV_INC@@NGHTTP2_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;..\;win32;..\..\isccfg\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
@END PKCS11
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
|
|
@ -184,7 +187,7 @@ copy InstallFiles ..\Build\Debug\
|
|||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
|
||||
<AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@@LIBUV_LIB@@LIBXML2_LIB@@ZLIB_LIB@ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@@LIBUV_LIB@@NGHTTP2_LIB@@LIBXML2_LIB@@ZLIB_LIB@ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>$(ProjectName).def</ModuleDefinitionFile>
|
||||
<ImportLibrary>.\$(Configuration)\$(ProjectName).lib</ImportLibrary>
|
||||
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
||||
|
|
@ -211,6 +214,9 @@ copy @OPENSSL_PATH@\LICENSE ..\Build\Release\OpenSSL-LICENSE
|
|||
echo Copying libuv DLL.
|
||||
copy @LIBUV_DLL@ ..\Build\Release\
|
||||
|
||||
echo Copying nghttp2 DLL.
|
||||
copy @NGHTTP2_DLL@ ..\Build\Release\
|
||||
|
||||
@IF LIBXML2
|
||||
echo Copying the libxml DLL.
|
||||
|
||||
|
|
@ -337,6 +343,7 @@ copy InstallFiles ..\Build\Release\
|
|||
<ClInclude Include="..\include\isc\tls.h" />
|
||||
<ClInclude Include="..\include\isc\tm.h" />
|
||||
<ClInclude Include="..\include\isc\types.h" />
|
||||
<ClInclude Include="..\include\isc\url.h" />
|
||||
<ClInclude Include="..\include\isc\utf8.h" />
|
||||
<ClInclude Include="..\include\isc\util.h" />
|
||||
@IF PKCS11
|
||||
|
|
@ -408,14 +415,15 @@ copy InstallFiles ..\Build\Release\
|
|||
<ClCompile Include="..\mem.c" />
|
||||
<ClCompile Include="..\mutexblock.c" />
|
||||
<ClCompile Include="..\netaddr.c" />
|
||||
<ClCompile Include="..\netmgr\http.c" />
|
||||
<ClCompile Include="..\netmgr\netmgr.c" />
|
||||
<ClCompile Include="..\netmgr\tcp.c" />
|
||||
<ClCompile Include="..\netmgr\udp.c" />
|
||||
<ClCompile Include="..\netmgr\uverr2result.c" />
|
||||
<ClCompile Include="..\netmgr\uv-compat.c" />
|
||||
<ClCompile Include="..\netmgr\tcpdns.c" />
|
||||
<ClCompile Include="..\netmgr\tlsstream.c" />
|
||||
<ClCompile Include="..\netmgr\udp.c" />
|
||||
<ClCompile Include="..\netmgr\tlsdns.c" />
|
||||
<ClCompile Include="..\netmgr\uv-compat.c" />
|
||||
<ClCompile Include="..\netmgr\uverr2result.c" />
|
||||
<ClCompile Include="..\netscope.c" />
|
||||
<ClCompile Include="..\nonce.c" />
|
||||
<ClCompile Include="..\openssl_shim.c" />
|
||||
|
|
@ -443,6 +451,7 @@ copy InstallFiles ..\Build\Release\
|
|||
<ClCompile Include="..\timer.c" />
|
||||
<ClCompile Include="..\tls.c" />
|
||||
<ClCompile Include="..\tm.c" />
|
||||
<ClCompile Include="..\url.c" />
|
||||
<ClCompile Include="..\utf8.c" />
|
||||
@IF PKCS11
|
||||
<ClCompile Include="..\pk11.c" />
|
||||
|
|
|
|||
|
|
@ -1887,6 +1887,7 @@
|
|||
./lib/isc/include/isc/tls.h C 2021
|
||||
./lib/isc/include/isc/tm.h C 2014,2016,2018,2019,2020,2021
|
||||
./lib/isc/include/isc/types.h C 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2012,2013,2014,2016,2017,2018,2019,2020,2021
|
||||
./lib/isc/include/isc/url.h C 2021
|
||||
./lib/isc/include/isc/utf8.h C 2020,2021
|
||||
./lib/isc/include/isc/util.h C 1998,1999,2000,2001,2004,2005,2006,2007,2010,2011,2012,2015,2016,2017,2018,2019,2020,2021
|
||||
./lib/isc/include/pk11/constants.h C 2014,2016,2017,2018,2019,2020,2021
|
||||
|
|
@ -1904,6 +1905,7 @@
|
|||
./lib/isc/mem_p.h C 2018,2019,2020,2021
|
||||
./lib/isc/mutexblock.c C 1999,2000,2001,2004,2005,2007,2011,2012,2016,2018,2019,2020,2021
|
||||
./lib/isc/netaddr.c C 1999,2000,2001,2002,2004,2005,2007,2010,2011,2012,2014,2015,2016,2017,2018,2019,2020,2021
|
||||
./lib/isc/netmgr/http.c C 2021
|
||||
./lib/isc/netmgr/netmgr-int.h C 2019,2020,2021
|
||||
./lib/isc/netmgr/netmgr.c C 2019,2020,2021
|
||||
./lib/isc/netmgr/tcp.c C 2019,2020,2021
|
||||
|
|
@ -2019,6 +2021,7 @@
|
|||
./lib/isc/unix/stdtime.c C 1999,2000,2001,2004,2005,2007,2016,2018,2019,2020,2021
|
||||
./lib/isc/unix/syslog.c C 2001,2004,2005,2007,2016,2018,2019,2020,2021
|
||||
./lib/isc/unix/time.c C 1998,1999,2000,2001,2003,2004,2005,2006,2007,2008,2011,2012,2014,2015,2016,2017,2018,2019,2020,2021
|
||||
./lib/isc/url.c C 2021
|
||||
./lib/isc/utf8.c C 2020,2021
|
||||
./lib/isc/win32/DLLMain.c C 2001,2004,2007,2016,2018,2019,2020,2021
|
||||
./lib/isc/win32/condition.c C 1998,1999,2000,2001,2004,2006,2007,2016,2018,2019,2020,2021
|
||||
|
|
|
|||
|
|
@ -221,6 +221,7 @@ my @substinc = ("GSSAPI_INC",
|
|||
"IDN_INC",
|
||||
"LIBXML2_INC",
|
||||
"LIBUV_INC",
|
||||
"NGHTTP2_INC",
|
||||
"OPENSSL_INC",
|
||||
"READLINE_INC",
|
||||
"ZLIB_INC");
|
||||
|
|
@ -235,6 +236,7 @@ my @substlib = ("GSSAPI_LIB",
|
|||
"KRB5_LIB",
|
||||
"LIBXML2_LIB",
|
||||
"LIBUV_LIB",
|
||||
"NGHTTP2_LIB",
|
||||
"OPENSSL_LIBCRYPTO",
|
||||
"OPENSSL_LIBSSL",
|
||||
"READLINE_LIB",
|
||||
|
|
@ -253,6 +255,7 @@ my @substdll = ("COMERR_DLL",
|
|||
"K5SPRT_DLL",
|
||||
"LIBXML2_DLL",
|
||||
"LIBUV_DLL",
|
||||
"NGHTTP2_DLL",
|
||||
"OPENSSL_DLLCRYPTO",
|
||||
"OPENSSL_DLLSSL",
|
||||
"WSHELP_DLL",
|
||||
|
|
@ -341,6 +344,7 @@ my @withlist = ("aes",
|
|||
"idn",
|
||||
"openssl",
|
||||
"libxml2",
|
||||
"nghttp2",
|
||||
"pkcs11",
|
||||
"pssuspend",
|
||||
"python",
|
||||
|
|
@ -389,6 +393,7 @@ my @help = (
|
|||
" with-samples build with sample programs\n",
|
||||
" with-openssl[=PATH] build with OpenSSL yes|path (mandatory)\n",
|
||||
" with-libuv[=PATH] build with libuv yes|path (mandatory)\n",
|
||||
" with-nghttp2[=PATH] build with nghttp2 yes|path (mandatory)\n",
|
||||
" with-pkcs11[=PATH] build with PKCS#11 support yes|no|provider-path\n",
|
||||
" with-gssapi[=PATH] build with MIT KfW GSSAPI yes|no|path\n",
|
||||
" with-libxml2[=PATH] build with libxml2 library yes|no|path\n",
|
||||
|
|
@ -431,6 +436,8 @@ my $use_stests = "no";
|
|||
my $use_samples = "no";
|
||||
my $use_libuv = "auto";
|
||||
my $libuv_path = "../../";
|
||||
my $nghttp2_path = "../../";
|
||||
my $use_nghttp2 = "auto";
|
||||
my $use_openssl = "auto";
|
||||
my $openssl_path = "../../";
|
||||
my $use_pkcs11 = "no";
|
||||
|
|
@ -758,6 +765,13 @@ sub mywith {
|
|||
$use_libuv = "yes";
|
||||
$libuv_path = $val;
|
||||
}
|
||||
} elsif ($key =~ /^nghttp2$/i) {
|
||||
if ($val =~ /^no$/i) {
|
||||
die "nghttp2 is required\n";
|
||||
} elsif ($val !~ /^yes$/i) {
|
||||
$use_nghttp2 = "yes";
|
||||
$nghttp2_path = $val;
|
||||
}
|
||||
} elsif ($key =~ /^pkcs11$/i) {
|
||||
if ($val =~ /^yes$/i) {
|
||||
$use_pkcs11 = "yes";
|
||||
|
|
@ -949,6 +963,7 @@ if ($verbose) {
|
|||
print "querytrace: disabled\n";
|
||||
}
|
||||
print "libuv-path: $libuv_path\n";
|
||||
print "nghttp2-path: $nghttp2_path\n";
|
||||
print "openssl-path: $openssl_path\n";
|
||||
if ($use_tests eq "yes") {
|
||||
print "tests: enabled\n";
|
||||
|
|
@ -1327,6 +1342,63 @@ if ($use_libuv eq "yes") {
|
|||
# $configdefh{"HAVE_UV_IMPORT"} = 1;
|
||||
}
|
||||
|
||||
# with-nghttp2
|
||||
if ($use_nghttp2 eq "auto") {
|
||||
if ($verbose) {
|
||||
print "checking for an nghttp2 built directory at sibling root\n";
|
||||
}
|
||||
opendir DIR, $nghttp2_path || die "No Directory: $!\n";
|
||||
my @dirlist = grep (/^nghttp2-[0-9]+\.[0-9]+\.[0-9]+$/i, readdir(DIR));
|
||||
closedir(DIR);
|
||||
|
||||
# Make sure we have something
|
||||
if (scalar(@dirlist) == 0) {
|
||||
die "can't find an nghttp2 at sibling root\n";
|
||||
}
|
||||
# Now see if we have a directory or just a file.
|
||||
# Make sure we are case insensitive
|
||||
my $file;
|
||||
foreach $file (sort {uc($b) cmp uc($a)} @dirlist) {
|
||||
if (-f File::Spec->catfile($nghttp2_path,
|
||||
$file,
|
||||
"include", "nghttp2", "nghttp2.h")) {
|
||||
$nghttp2_path = File::Spec->catdir($nghttp2_path, $file);
|
||||
$use_nghttp2 = "yes";
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# If we have one use it otherwise report the error
|
||||
if ($use_nghttp2 eq "auto") {
|
||||
die "can't find an nghttp2 built directory at sibling root\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($use_nghttp2 eq "yes") {
|
||||
$nghttp2_path = File::Spec->rel2abs($nghttp2_path);
|
||||
if ($verbose) {
|
||||
print "checking for nghttp2 directory at \"$nghttp2_path\"\n";
|
||||
}
|
||||
if (!-f File::Spec->catfile($nghttp2_path,
|
||||
"include", "nghttp2", "nghttp2.h")) {
|
||||
die "can't find nghttp2 nghttp2.h include\n";
|
||||
}
|
||||
my $nghttp2_inc = File::Spec->catdir($nghttp2_path, "include");
|
||||
my $nghttp2_bindir = File::Spec->catdir($nghttp2_path, "bin");
|
||||
my $nghttp2_libdir = File::Spec->catdir($nghttp2_path, "lib");
|
||||
my $nghttp2_dll = File::Spec->catfile($nghttp2_bindir, "nghttp2.dll");
|
||||
my $nghttp2_lib = File::Spec->catfile($nghttp2_libdir, "nghttp2.lib");
|
||||
if (!-f $nghttp2_lib) {
|
||||
die "can't find nghttp2.lib library\n";
|
||||
}
|
||||
if (!-f $nghttp2_dll) {
|
||||
die "can't find nghttp2.dll library\n";
|
||||
}
|
||||
$configinc{"NGHTTP2_INC"} = "$nghttp2_inc";
|
||||
$configlib{"NGHTTP2_LIB"} = "$nghttp2_lib";
|
||||
$configdll{"NGHTTP2_DLL"} = "$nghttp2_dll";
|
||||
}
|
||||
|
||||
# with-openssl
|
||||
if ($use_openssl eq "auto") {
|
||||
if ($verbose) {
|
||||
|
|
@ -2433,6 +2505,7 @@ sub makeinstallfile {
|
|||
print LOUT "libdns.dll-BCFT\n";
|
||||
print LOUT "libirs.dll-BCFT\n";
|
||||
print LOUT "libns.dll-BCFT\n";
|
||||
print LOUT "nghttp2.dll-BCFT\n";
|
||||
print LOUT "uv.dll-BCFT\n";
|
||||
if ($use_openssl eq "yes") {
|
||||
my $v;
|
||||
|
|
|
|||
Loading…
Reference in a new issue