Commit 23c7373d authored by Evan Hunt's avatar Evan Hunt
Browse files

restore "blackhole" functionality

the blackhole ACL was accidentally disabled with respect to client
queries during the netmgr conversion.

in order to make this work for TCP, it was necessary to add a return
code to the accept callback functions passed to isc_nm_listentcp() and
isc_nm_listentcpdns().
parent e3ee1380
......@@ -24,6 +24,47 @@ typedef enum {
NMEV_SHUTDOWN
} isc_nm_eventtype;
typedef void (*isc_nm_recv_cb_t)(isc_nmhandle_t *handle, isc_result_t eresult,
isc_region_t *region, void *cbarg);
/*%<
* Callback function to be used when receiving a packet.
*
* 'handle' the handle that can be used to send back the answer.
* 'eresult' the result of the event.
* 'region' contains the received data, if any. It will be freed
* after return by caller.
* 'cbarg' the callback argument passed to isc_nm_listenudp(),
* isc_nm_listentcpdns(), or isc_nm_read().
*/
typedef isc_result_t (*isc_nm_accept_cb_t)(isc_nmhandle_t *handle,
isc_result_t result, void *cbarg);
/*%<
* Callback function to be used when accepting a connection. (This differs
* from isc_nm_cb_t below in that it returns a result code.)
*
* 'handle' the handle that can be used to send back the answer.
* 'eresult' the result of the event.
* 'cbarg' the callback argument passed to isc_nm_listentcp() or
* isc_nm_listentcpdns().
*/
typedef void (*isc_nm_cb_t)(isc_nmhandle_t *handle, isc_result_t result,
void *cbarg);
/*%<
* Callback function for other network completion events (send, connect).
*
* 'handle' the handle on which the event took place.
* 'eresult' the result of the event.
* 'cbarg' the callback argument passed to isc_nm_send(),
* isc_nm_tcp_connect(), or isc_nm_listentcp()
*/
typedef void (*isc_nm_opaquecb_t)(void *arg);
/*%<
* Opaque callback function, used for isc_nmhandle 'reset' and 'free'
* callbacks.
*/
isc_nm_t *
isc_nm_start(isc_mem_t *mctx, uint32_t workers);
/*%<
......@@ -89,8 +130,6 @@ isc_nmhandle_getdata(isc_nmhandle_t *handle);
void *
isc_nmhandle_getextra(isc_nmhandle_t *handle);
typedef void (*isc_nm_opaquecb_t)(void *arg);
bool
isc_nmhandle_is_stream(isc_nmhandle_t *handle);
......@@ -122,31 +161,6 @@ isc_nmhandle_netmgr(isc_nmhandle_t *handle);
* Return a pointer to the netmgr object for the given handle.
*/
typedef void (*isc_nm_recv_cb_t)(isc_nmhandle_t *handle, isc_result_t eresult,
isc_region_t *region, void *cbarg);
/*%<
* Callback function to be used when receiving a packet.
*
* 'handle' the handle that can be used to send back the answer.
* 'eresult' the result of the event.
* 'region' contains the received data, if any. It will be freed
* after return by caller.
* 'cbarg' the callback argument passed to isc_nm_listenudp(),
* isc_nm_listentcpdns(), or isc_nm_read().
*/
typedef void (*isc_nm_cb_t)(isc_nmhandle_t *handle, isc_result_t eresult,
void *cbarg);
/*%<
* Callback function for other network completion events (send, connect,
* accept).
*
* 'handle' the handle on which the event took place.
* 'eresult' the result of the event.
* 'cbarg' the callback argument passed to isc_nm_send(),
* isc_nm_tcp_connect(), or isc_nm_listentcp()
*/
isc_result_t
isc_nm_listenudp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
void *cbarg, size_t extrasize, isc_nmsocket_t **sockp);
......@@ -226,9 +240,10 @@ isc_nm_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
*/
isc_result_t
isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_cb_t cb,
void *cbarg, size_t extrahandlesize, int backlog,
isc_quota_t *quota, isc_nmsocket_t **sockp);
isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface,
isc_nm_accept_cb_t accept_cb, void *accept_cbarg,
size_t extrahandlesize, int backlog, isc_quota_t *quota,
isc_nmsocket_t **sockp);
/*%<
* Start listening for raw messages over the TCP interface 'iface', using
* net manager 'mgr'.
......@@ -236,8 +251,8 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_cb_t cb,
* On success, 'sockp' will be updated to contain a new listening TCP
* socket.
*
* When a message is received on the socket, 'cb' will be called with 'cbarg'
* as its argument.
* When connection is accepted on the socket, 'accept_cb' will be called with
* 'accept_cbarg' as its argument. The callback is expected to start a read.
*
* When handles are allocated for the socket, 'extrasize' additional bytes
* will be allocated along with the handle for an associated object.
......@@ -267,9 +282,9 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
isc_result_t
isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
void *cbarg, isc_nm_cb_t accept_cb, void *accept_cbarg,
size_t extrahandlesize, int backlog, isc_quota_t *quota,
isc_nmsocket_t **sockp);
void *cbarg, isc_nm_accept_cb_t accept_cb,
void *accept_cbarg, size_t extrahandlesize, int backlog,
isc_quota_t *quota, isc_nmsocket_t **sockp);
/*%<
* Start listening for DNS messages over the TCP interface 'iface', using
* net manager 'mgr'.
......@@ -283,7 +298,7 @@ isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
* When a complete DNS message is received on the socket, 'cb' will be
* called with 'cbarg' as its argument.
*
* When a new TCP connection is accepted, 'accept_cb' will be called
* When a new TCPDNS connection is accepted, 'accept_cb' will be called
* with 'accept_cbarg' as its argument.
*
* When handles are allocated for the socket, 'extrasize' additional bytes
......
......@@ -150,7 +150,7 @@ typedef enum isc__netievent_type {
*/
typedef union {
isc_nm_recv_cb_t recv;
isc_nm_cb_t accept;
isc_nm_accept_cb_t accept;
} isc__nm_readcb_t;
typedef union {
......@@ -160,7 +160,7 @@ typedef union {
typedef union {
isc_nm_recv_cb_t recv;
isc_nm_cb_t accept;
isc_nm_accept_cb_t accept;
isc_nm_cb_t send;
isc_nm_cb_t connect;
} isc__nm_cb_t;
......
......@@ -243,9 +243,10 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
}
isc_result_t
isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_cb_t cb,
void *cbarg, size_t extrahandlesize, int backlog,
isc_quota_t *quota, isc_nmsocket_t **sockp) {
isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface,
isc_nm_accept_cb_t accept_cb, void *accept_cbarg,
size_t extrahandlesize, int backlog, isc_quota_t *quota,
isc_nmsocket_t **sockp) {
isc_nmsocket_t *nsock = NULL;
isc__netievent_tcplisten_t *ievent = NULL;
......@@ -253,8 +254,8 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_cb_t cb,
nsock = isc_mem_get(mgr->mctx, sizeof(*nsock));
isc__nmsocket_init(nsock, mgr, isc_nm_tcplistener, iface);
nsock->accept_cb.accept = cb;
nsock->accept_cbarg = cbarg;
nsock->accept_cb.accept = accept_cb;
nsock->accept_cbarg = accept_cbarg;
nsock->extrahandlesize = extrahandlesize;
nsock->backlog = backlog;
nsock->result = ISC_R_SUCCESS;
......
......@@ -102,7 +102,7 @@ dnstcp_readtimeout(uv_timer_t *timer) {
/*
* Accept callback for TCP-DNS connection.
*/
static void
static isc_result_t
dnslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
isc_nmsocket_t *dnslistensock = (isc_nmsocket_t *)cbarg;
isc_nmsocket_t *dnssock = NULL;
......@@ -110,14 +110,16 @@ dnslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
REQUIRE(VALID_NMSOCK(dnslistensock));
REQUIRE(dnslistensock->type == isc_nm_tcpdnslistener);
/* If accept() was unnsuccessful we can't do anything */
if (result != ISC_R_SUCCESS) {
return;
return (result);
}
if (dnslistensock->accept_cb.accept != NULL) {
dnslistensock->accept_cb.accept(handle, ISC_R_SUCCESS,
dnslistensock->accept_cbarg);
result = dnslistensock->accept_cb.accept(
handle, ISC_R_SUCCESS, dnslistensock->accept_cbarg);
if (result != ISC_R_SUCCESS) {
return (result);
}
}
/* We need to create a 'wrapper' dnssocket for this connection */
......@@ -144,12 +146,15 @@ dnslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
dnssock->timer_initialized = true;
uv_timer_start(&dnssock->timer, dnstcp_readtimeout,
dnssock->read_timeout, 0);
isc_nmhandle_ref(handle);
result = isc_nm_read(handle, dnslisten_readcb, dnssock);
if (result != ISC_R_SUCCESS) {
isc_nmhandle_unref(handle);
}
isc__nmsocket_detach(&dnssock);
return (ISC_R_SUCCESS);
}
/*
......@@ -306,9 +311,9 @@ dnslisten_readcb(isc_nmhandle_t *handle, isc_result_t eresult,
*/
isc_result_t
isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
void *cbarg, isc_nm_cb_t accept_cb, void *accept_cbarg,
size_t extrahandlesize, int backlog, isc_quota_t *quota,
isc_nmsocket_t **sockp) {
void *cbarg, isc_nm_accept_cb_t accept_cb,
void *accept_cbarg, size_t extrahandlesize, int backlog,
isc_quota_t *quota, isc_nmsocket_t **sockp) {
/* A 'wrapper' socket object with outer set to true TCP socket */
isc_nmsocket_t *dnslistensock = isc_mem_get(mgr->mctx,
sizeof(*dnslistensock));
......
......@@ -1625,7 +1625,6 @@ void
ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
isc_region_t *region, void *arg) {
ns_client_t *client;
bool newclient = false;
ns_clientmgr_t *mgr;
ns_interface_t *ifp;
isc_result_t result;
......@@ -1724,29 +1723,23 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
}
#endif /* if NS_CLIENT_DROPPORT */
env = ns_interfacemgr_getaclenv(client->manager->interface->mgr);
if (client->sctx->blackholeacl != NULL &&
(dns_acl_match(&netaddr, NULL, client->sctx->blackholeacl, env,
&match, NULL) == ISC_R_SUCCESS) &&
match > 0)
{
ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
"dropped request: blackholed peer");
isc_task_unpause(client->task);
return;
}
ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT,
ISC_LOG_DEBUG(3), "%s request",
TCP_CLIENT(client) ? "TCP" : "UDP");
/*
* Check the blackhole ACL for UDP only, since TCP is done in
* client_newconn.
*/
env = ns_interfacemgr_getaclenv(client->manager->interface->mgr);
if (newclient) {
if (client->sctx->blackholeacl != NULL &&
(dns_acl_match(&netaddr, NULL, client->sctx->blackholeacl,
env, &match, NULL) == ISC_R_SUCCESS) &&
match > 0)
{
ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
"blackholed UDP datagram");
isc_task_unpause(client->task);
return;
}
}
result = dns_message_peekheader(buffer, &id, &flags);
if (result != ISC_R_SUCCESS) {
/*
......@@ -2213,17 +2206,36 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
isc_task_unpause(client->task);
}
void
isc_result_t
ns__client_tcpconn(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
ns_server_t *sctx = (ns_server_t *)arg;
ns_interface_t *ifp = (ns_interface_t *)arg;
dns_aclenv_t *env = ns_interfacemgr_getaclenv(ifp->mgr);
ns_server_t *sctx = ns_interfacemgr_getserver(ifp->mgr);
unsigned int tcpquota;
isc_sockaddr_t peeraddr;
isc_netaddr_t netaddr;
int match;
UNUSED(handle);
UNUSED(result);
if (handle != NULL) {
peeraddr = isc_nmhandle_peeraddr(handle);
isc_netaddr_fromsockaddr(&netaddr, &peeraddr);
if (sctx->blackholeacl != NULL &&
(dns_acl_match(&netaddr, NULL, sctx->blackholeacl, env,
&match, NULL) == ISC_R_SUCCESS) &&
match > 0)
{
return (ISC_R_CONNREFUSED);
}
}
tcpquota = isc_quota_getused(&sctx->tcpquota);
ns_stats_update_if_greater(sctx->nsstats, ns_statscounter_tcphighwater,
tcpquota);
return (ISC_R_SUCCESS);
}
static void
......
......@@ -476,7 +476,7 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
* (Not intended for use outside this module and associated tests.)
*/
void
isc_result_t
ns__client_tcpconn(isc_nmhandle_t *handle, isc_result_t result, void *arg);
/*%<
......
......@@ -197,6 +197,12 @@ ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr);
bool
ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, const isc_sockaddr_t *addr);
ns_server_t *
ns_interfacemgr_getserver(ns_interfacemgr_t *mgr);
/*%<
* Returns the ns_server object associated with the interface manager.
*/
ns_interface_t *
ns__interfacemgr_getif(ns_interfacemgr_t *mgr);
ns_interface_t *
......
......@@ -467,7 +467,7 @@ ns_interface_listentcp(ns_interface_t *ifp) {
result = isc_nm_listentcpdns(
ifp->mgr->nm, (isc_nmiface_t *)&ifp->addr, ns__client_request,
ifp, ns__client_tcpconn, ifp->mgr->sctx, sizeof(ns_client_t),
ifp, ns__client_tcpconn, ifp, sizeof(ns_client_t),
ifp->mgr->backlog, &ifp->mgr->sctx->tcpquota,
&ifp->tcplistensocket);
if (result != ISC_R_SUCCESS) {
......@@ -481,7 +481,12 @@ ns_interface_listentcp(ns_interface_t *ifp) {
* this is necessary because we are adding to the TCP quota just
* by listening.
*/
ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp->mgr->sctx);
result = ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp);
if (result != ISC_R_SUCCESS) {
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
"connecting TCP socket: %s",
isc_result_totext(result));
}
#if 0
#ifndef ISC_ALLOW_MAPPED
......@@ -1267,6 +1272,13 @@ ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr,
return (result);
}
ns_server_t *
ns_interfacemgr_getserver(ns_interfacemgr_t *mgr) {
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
return (mgr->sctx);
}
ns_interface_t *
ns__interfacemgr_getif(ns_interfacemgr_t *mgr) {
ns_interface_t *head;
......
......@@ -55,6 +55,7 @@ ns_interfacemgr_create
ns_interfacemgr_detach
ns_interfacemgr_dumprecursing
ns_interfacemgr_getaclenv
ns_interfacemgr_getserver
ns_interfacemgr_islistening
ns_interfacemgr_listeningon
ns_interfacemgr_scan
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment