mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +00:00
Merge branch 'ondrej-further-dns_validator-refactoring' into 'main'
additional refactoring of dns_validator See merge request isc-projects/bind9!7546
This commit is contained in:
4
CHANGES
4
CHANGES
@@ -1,3 +1,7 @@
|
||||
6103. [func] All uses of the isc_task and isc_event APIs have
|
||||
been refactored to use isc_loop instead, and the
|
||||
original APIs have been removed. [GL #3797]
|
||||
|
||||
6102. [cleanup] Several nugatory headers have been removed from libisc.
|
||||
[GL !7464]
|
||||
|
||||
|
@@ -48,8 +48,9 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <isc/job.h>
|
||||
#include <isc/lang.h>
|
||||
#include <isc/mutex.h>
|
||||
#include <isc/refcount.h>
|
||||
|
||||
#include <dns/fixedname.h>
|
||||
#include <dns/rdataset.h>
|
||||
@@ -58,31 +59,44 @@
|
||||
|
||||
#include <dst/dst.h>
|
||||
|
||||
#define DNS_VALIDATOR_NOQNAMEPROOF 0
|
||||
#define DNS_VALIDATOR_NODATAPROOF 1
|
||||
#define DNS_VALIDATOR_NOWILDCARDPROOF 2
|
||||
#define DNS_VALIDATOR_CLOSESTENCLOSER 3
|
||||
|
||||
/*%
|
||||
* A dns_valstatus_t is sent when a 'validation' completes.
|
||||
* A validator object represents a validation in progress.
|
||||
* \brief
|
||||
* 'name', 'rdataset', 'sigrdataset', and 'message' are the values that were
|
||||
* supplied when dns_validator_create() was called. They are returned to the
|
||||
* caller so that they may be freed.
|
||||
*
|
||||
* If the RESULT is ISC_R_SUCCESS and the answer is secure then
|
||||
* proofs[] will contain the names of the NSEC records that hold the
|
||||
* various proofs. Note the same name may appear multiple times.
|
||||
*
|
||||
* The structure is freed by dns_validator_destroy().
|
||||
* Clients are strongly discouraged from using this type directly, with
|
||||
* the exception of the 'link' field, which may be used directly for
|
||||
* whatever purpose the client desires.
|
||||
*/
|
||||
typedef struct dns_valstatus {
|
||||
dns_validator_t *validator;
|
||||
isc_result_t result;
|
||||
struct dns_validator {
|
||||
unsigned int magic;
|
||||
dns_view_t *view;
|
||||
isc_loopmgr_t *loopmgr;
|
||||
uint32_t tid;
|
||||
isc_refcount_t references;
|
||||
|
||||
isc_mem_t *mctx;
|
||||
|
||||
/*
|
||||
* Name and type of the response to be validated.
|
||||
*/
|
||||
dns_fixedname_t fname;
|
||||
/* Name and type of the response to be validated. */
|
||||
dns_name_t *name;
|
||||
dns_rdatatype_t type;
|
||||
|
||||
/*
|
||||
* Callback and argument to use to inform the caller
|
||||
* that validation is complete.
|
||||
*/
|
||||
isc_job_cb cb;
|
||||
void *arg;
|
||||
|
||||
/* Validation options (_DEFER, _NONTA, etc). */
|
||||
unsigned int options;
|
||||
|
||||
/*
|
||||
* Results of a completed validation.
|
||||
*/
|
||||
isc_result_t result;
|
||||
|
||||
/*
|
||||
* Rdata and RRSIG (if any) for positive responses.
|
||||
*/
|
||||
@@ -105,40 +119,17 @@ typedef struct dns_valstatus {
|
||||
* Answer is secure.
|
||||
*/
|
||||
bool secure;
|
||||
} dns_valstatus_t;
|
||||
|
||||
#define DNS_VALIDATOR_NOQNAMEPROOF 0
|
||||
#define DNS_VALIDATOR_NODATAPROOF 1
|
||||
#define DNS_VALIDATOR_NOWILDCARDPROOF 2
|
||||
#define DNS_VALIDATOR_CLOSESTENCLOSER 3
|
||||
|
||||
/*%
|
||||
* A validator object represents a validation in progress.
|
||||
* \brief
|
||||
* Clients are strongly discouraged from using this type directly, with
|
||||
* the exception of the 'link' field, which may be used directly for
|
||||
* whatever purpose the client desires.
|
||||
*/
|
||||
struct dns_validator {
|
||||
/* Unlocked. */
|
||||
unsigned int magic;
|
||||
isc_mutex_t lock;
|
||||
dns_view_t *view;
|
||||
/* Locked by lock. */
|
||||
unsigned int options;
|
||||
/* Internal validator state */
|
||||
unsigned int attributes;
|
||||
dns_valstatus_t *vstat;
|
||||
dns_fetch_t *fetch;
|
||||
dns_validator_t *subvalidator;
|
||||
dns_validator_t *parent;
|
||||
dns_keytable_t *keytable;
|
||||
dst_key_t *key;
|
||||
dns_rdata_rrsig_t *siginfo;
|
||||
isc_loop_t *loop;
|
||||
isc_job_cb cb;
|
||||
void *arg;
|
||||
unsigned int labels;
|
||||
dns_rdataset_t *currentset;
|
||||
dns_rdataset_t *nxset;
|
||||
dns_rdataset_t *keyset;
|
||||
dns_rdataset_t *dsset;
|
||||
dns_rdataset_t fdsset;
|
||||
@@ -169,7 +160,7 @@ isc_result_t
|
||||
dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
|
||||
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
|
||||
dns_message_t *message, unsigned int options,
|
||||
isc_loop_t *loop, isc_job_cb cb, void *arg,
|
||||
isc_loopmgr_t *loop, isc_job_cb cb, void *arg,
|
||||
dns_validator_t **validatorp);
|
||||
/*%<
|
||||
* Start a DNSSEC validation.
|
||||
@@ -238,10 +229,24 @@ dns_validator_destroy(dns_validator_t **validatorp);
|
||||
* Requires:
|
||||
*\li '*validatorp' points to a valid DNSSEC validator.
|
||||
* \li The validator must have completed and sent its completion
|
||||
* event.
|
||||
* event.
|
||||
*
|
||||
* Ensures:
|
||||
*\li All resources used by the validator are freed.
|
||||
*/
|
||||
|
||||
#if DNS_VALIDATOR_TRACE
|
||||
#define dns_validator_ref(ptr) \
|
||||
dns_validator__ref(ptr, __func__, __FILE__, __LINE__)
|
||||
#define dns_validator_unref(ptr) \
|
||||
dns_validator__unref(ptr, __func__, __FILE__, __LINE__)
|
||||
#define dns_validator_attach(ptr, ptrp) \
|
||||
dns_validator__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
|
||||
#define dns_validator_detach(ptrp) \
|
||||
dns_validator__detach(ptrp, __func__, __FILE__, __LINE__)
|
||||
ISC_REFCOUNT_TRACE_DECL(dns_validator);
|
||||
#else
|
||||
ISC_REFCOUNT_DECL(dns_validator);
|
||||
#endif
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
@@ -961,8 +961,7 @@ set_stats(dns_resolver_t *res, isc_statscounter_t counter, uint64_t val) {
|
||||
static isc_result_t
|
||||
valcreate(fetchctx_t *fctx, dns_message_t *message, dns_adbaddrinfo_t *addrinfo,
|
||||
dns_name_t *name, dns_rdatatype_t type, dns_rdataset_t *rdataset,
|
||||
dns_rdataset_t *sigrdataset, unsigned int valoptions,
|
||||
isc_loop_t *loop) {
|
||||
dns_rdataset_t *sigrdataset, unsigned int valoptions) {
|
||||
dns_validator_t *validator = NULL;
|
||||
dns_valarg_t *valarg = NULL;
|
||||
isc_result_t result;
|
||||
@@ -980,9 +979,9 @@ valcreate(fetchctx_t *fctx, dns_message_t *message, dns_adbaddrinfo_t *addrinfo,
|
||||
valoptions &= ~DNS_VALIDATOR_DEFER;
|
||||
}
|
||||
|
||||
result = dns_validator_create(fctx->res->view, name, type, rdataset,
|
||||
sigrdataset, message, valoptions, loop,
|
||||
validated, valarg, &validator);
|
||||
result = dns_validator_create(
|
||||
fctx->res->view, name, type, rdataset, sigrdataset, message,
|
||||
valoptions, fctx->res->loopmgr, validated, valarg, &validator);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
inc_stats(fctx->res, dns_resstatscounter_val);
|
||||
if ((valoptions & DNS_VALIDATOR_DEFER) == 0) {
|
||||
@@ -5312,8 +5311,7 @@ has_000_label(dns_rdataset_t *nsecset) {
|
||||
*/
|
||||
static void
|
||||
validated(void *arg) {
|
||||
dns_valstatus_t *vstat = (dns_valstatus_t *)arg;
|
||||
dns_validator_t *val = vstat->validator;
|
||||
dns_validator_t *val = (dns_validator_t *)arg;
|
||||
dns_adbaddrinfo_t *addrinfo = NULL;
|
||||
dns_dbnode_t *node = NULL;
|
||||
dns_dbnode_t *nsnode = NULL;
|
||||
@@ -5354,8 +5352,8 @@ validated(void *arg) {
|
||||
res = fctx->res;
|
||||
addrinfo = valarg->addrinfo;
|
||||
|
||||
message = vstat->message;
|
||||
fctx->vresult = vstat->result;
|
||||
message = val->message;
|
||||
fctx->vresult = val->result;
|
||||
|
||||
LOCK(&fctx->lock);
|
||||
ISC_LIST_UNLINK(fctx->validators, val, link);
|
||||
@@ -5366,14 +5364,14 @@ validated(void *arg) {
|
||||
* Destroy the validator early so that we can
|
||||
* destroy the fctx if necessary. Save the wildcard name.
|
||||
*/
|
||||
if (vstat->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
|
||||
if (val->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
|
||||
wild = dns_fixedname_initname(&fwild);
|
||||
dns_name_copy(dns_fixedname_name(&val->wild), wild);
|
||||
}
|
||||
|
||||
isc_mem_put(fctx->mctx, valarg, sizeof(*valarg));
|
||||
|
||||
negative = (vstat->rdataset == NULL);
|
||||
negative = (val->rdataset == NULL);
|
||||
|
||||
LOCK(&fctx->lock);
|
||||
sentresponse = ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0);
|
||||
@@ -5394,13 +5392,13 @@ validated(void *arg) {
|
||||
* If chaining, we need to make sure that the right result code
|
||||
* is returned, and that the rdatasets are bound.
|
||||
*/
|
||||
if (vstat->result == ISC_R_SUCCESS && !negative &&
|
||||
vstat->rdataset != NULL && CHAINING(vstat->rdataset))
|
||||
if (val->result == ISC_R_SUCCESS && !negative &&
|
||||
val->rdataset != NULL && CHAINING(val->rdataset))
|
||||
{
|
||||
if (vstat->rdataset->type == dns_rdatatype_cname) {
|
||||
if (val->rdataset->type == dns_rdatatype_cname) {
|
||||
eresult = DNS_R_CNAME;
|
||||
} else {
|
||||
INSIST(vstat->rdataset->type == dns_rdatatype_dname);
|
||||
INSIST(val->rdataset->type == dns_rdatatype_dname);
|
||||
eresult = DNS_R_DNAME;
|
||||
}
|
||||
chaining = true;
|
||||
@@ -5431,28 +5429,26 @@ validated(void *arg) {
|
||||
}
|
||||
}
|
||||
|
||||
if (vstat->result != ISC_R_SUCCESS) {
|
||||
if (val->result != ISC_R_SUCCESS) {
|
||||
FCTXTRACE("validation failed");
|
||||
inc_stats(res, dns_resstatscounter_valfail);
|
||||
fctx->valfail++;
|
||||
fctx->vresult = vstat->result;
|
||||
fctx->vresult = val->result;
|
||||
if (fctx->vresult != DNS_R_BROKENCHAIN) {
|
||||
result = ISC_R_NOTFOUND;
|
||||
if (vstat->rdataset != NULL) {
|
||||
result = dns_db_findnode(
|
||||
fctx->cache, vstat->name, true, &node);
|
||||
if (val->rdataset != NULL) {
|
||||
result = dns_db_findnode(fctx->cache, val->name,
|
||||
true, &node);
|
||||
}
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
(void)dns_db_deleterdataset(fctx->cache, node,
|
||||
NULL, vstat->type,
|
||||
0);
|
||||
NULL, val->type, 0);
|
||||
}
|
||||
if (result == ISC_R_SUCCESS &&
|
||||
vstat->sigrdataset != NULL)
|
||||
if (result == ISC_R_SUCCESS && val->sigrdataset != NULL)
|
||||
{
|
||||
(void)dns_db_deleterdataset(
|
||||
fctx->cache, node, NULL,
|
||||
dns_rdatatype_rrsig, vstat->type);
|
||||
dns_rdatatype_rrsig, val->type);
|
||||
}
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
dns_db_detachnode(fctx->cache, &node);
|
||||
@@ -5464,21 +5460,20 @@ validated(void *arg) {
|
||||
* validation.
|
||||
*/
|
||||
result = ISC_R_NOTFOUND;
|
||||
if (vstat->rdataset != NULL) {
|
||||
result = dns_db_findnode(
|
||||
fctx->cache, vstat->name, true, &node);
|
||||
if (val->rdataset != NULL) {
|
||||
result = dns_db_findnode(fctx->cache, val->name,
|
||||
true, &node);
|
||||
}
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
(void)dns_db_addrdataset(
|
||||
fctx->cache, node, NULL, now,
|
||||
vstat->rdataset, 0, NULL);
|
||||
val->rdataset, 0, NULL);
|
||||
}
|
||||
if (result == ISC_R_SUCCESS &&
|
||||
vstat->sigrdataset != NULL)
|
||||
if (result == ISC_R_SUCCESS && val->sigrdataset != NULL)
|
||||
{
|
||||
(void)dns_db_addrdataset(
|
||||
fctx->cache, node, NULL, now,
|
||||
vstat->sigrdataset, 0, NULL);
|
||||
val->sigrdataset, 0, NULL);
|
||||
}
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
dns_db_detachnode(fctx->cache, &node);
|
||||
@@ -5539,7 +5534,7 @@ validated(void *arg) {
|
||||
covers = fctx->type;
|
||||
}
|
||||
|
||||
result = dns_db_findnode(fctx->cache, vstat->name, true, &node);
|
||||
result = dns_db_findnode(fctx->cache, val->name, true, &node);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
/* fctx->lock unlocked in noanswer_response */
|
||||
goto noanswer_response;
|
||||
@@ -5559,7 +5554,7 @@ validated(void *arg) {
|
||||
|
||||
result = ncache_adderesult(message, fctx->cache, node, covers,
|
||||
now, fctx->res->view->minncachettl,
|
||||
ttl, vstat->optout, vstat->secure,
|
||||
ttl, val->optout, val->secure,
|
||||
ardataset, &eresult);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto noanswer_response;
|
||||
@@ -5571,28 +5566,27 @@ validated(void *arg) {
|
||||
|
||||
FCTXTRACE("validation OK");
|
||||
|
||||
if (vstat->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
|
||||
if (val->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
|
||||
result = dns_rdataset_addnoqname(
|
||||
vstat->rdataset,
|
||||
vstat->proofs[DNS_VALIDATOR_NOQNAMEPROOF]);
|
||||
val->rdataset, val->proofs[DNS_VALIDATOR_NOQNAMEPROOF]);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
INSIST(vstat->sigrdataset != NULL);
|
||||
vstat->sigrdataset->ttl = vstat->rdataset->ttl;
|
||||
if (vstat->proofs[DNS_VALIDATOR_CLOSESTENCLOSER] != NULL) {
|
||||
INSIST(val->sigrdataset != NULL);
|
||||
val->sigrdataset->ttl = val->rdataset->ttl;
|
||||
if (val->proofs[DNS_VALIDATOR_CLOSESTENCLOSER] != NULL) {
|
||||
result = dns_rdataset_addclosest(
|
||||
vstat->rdataset,
|
||||
vstat->proofs[DNS_VALIDATOR_CLOSESTENCLOSER]);
|
||||
val->rdataset,
|
||||
val->proofs[DNS_VALIDATOR_CLOSESTENCLOSER]);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
}
|
||||
} else if (vstat->rdataset->trust == dns_trust_answer &&
|
||||
vstat->rdataset->type != dns_rdatatype_rrsig)
|
||||
} else if (val->rdataset->trust == dns_trust_answer &&
|
||||
val->rdataset->type != dns_rdatatype_rrsig)
|
||||
{
|
||||
isc_result_t tresult;
|
||||
dns_name_t *noqname = NULL;
|
||||
tresult = findnoqname(fctx, message, vstat->name,
|
||||
vstat->rdataset->type, &noqname);
|
||||
tresult = findnoqname(fctx, message, val->name,
|
||||
val->rdataset->type, &noqname);
|
||||
if (tresult == ISC_R_SUCCESS && noqname != NULL) {
|
||||
tresult = dns_rdataset_addnoqname(vstat->rdataset,
|
||||
tresult = dns_rdataset_addnoqname(val->rdataset,
|
||||
noqname);
|
||||
RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
|
||||
}
|
||||
@@ -5604,7 +5598,7 @@ validated(void *arg) {
|
||||
* rdatasets to the first event on the fetch
|
||||
* event list.
|
||||
*/
|
||||
result = dns_db_findnode(fctx->cache, vstat->name, true, &node);
|
||||
result = dns_db_findnode(fctx->cache, val->name, true, &node);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto noanswer_response;
|
||||
}
|
||||
@@ -5613,8 +5607,8 @@ validated(void *arg) {
|
||||
if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0) {
|
||||
options = DNS_DBADD_PREFETCH;
|
||||
}
|
||||
result = dns_db_addrdataset(fctx->cache, node, NULL, now,
|
||||
vstat->rdataset, options, ardataset);
|
||||
result = dns_db_addrdataset(fctx->cache, node, NULL, now, val->rdataset,
|
||||
options, ardataset);
|
||||
if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED) {
|
||||
goto noanswer_response;
|
||||
}
|
||||
@@ -5624,9 +5618,9 @@ validated(void *arg) {
|
||||
} else {
|
||||
eresult = DNS_R_NCACHENXRRSET;
|
||||
}
|
||||
} else if (vstat->sigrdataset != NULL) {
|
||||
} else if (val->sigrdataset != NULL) {
|
||||
result = dns_db_addrdataset(fctx->cache, node, NULL, now,
|
||||
vstat->sigrdataset, options,
|
||||
val->sigrdataset, options,
|
||||
asigrdataset);
|
||||
if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED) {
|
||||
goto noanswer_response;
|
||||
@@ -5760,25 +5754,24 @@ answer_response:
|
||||
/*
|
||||
* Add the wild card entry.
|
||||
*/
|
||||
if (vstat->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL &&
|
||||
vstat->rdataset != NULL &&
|
||||
dns_rdataset_isassociated(vstat->rdataset) &&
|
||||
vstat->rdataset->trust == dns_trust_secure &&
|
||||
vstat->sigrdataset != NULL &&
|
||||
dns_rdataset_isassociated(vstat->sigrdataset) &&
|
||||
vstat->sigrdataset->trust == dns_trust_secure && wild != NULL)
|
||||
if (val->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL &&
|
||||
val->rdataset != NULL && dns_rdataset_isassociated(val->rdataset) &&
|
||||
val->rdataset->trust == dns_trust_secure &&
|
||||
val->sigrdataset != NULL &&
|
||||
dns_rdataset_isassociated(val->sigrdataset) &&
|
||||
val->sigrdataset->trust == dns_trust_secure && wild != NULL)
|
||||
{
|
||||
dns_dbnode_t *wnode = NULL;
|
||||
|
||||
result = dns_db_findnode(fctx->cache, wild, true, &wnode);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
result = dns_db_addrdataset(fctx->cache, wnode, NULL,
|
||||
now, vstat->rdataset, 0,
|
||||
now, val->rdataset, 0,
|
||||
NULL);
|
||||
}
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
(void)dns_db_addrdataset(fctx->cache, wnode, NULL, now,
|
||||
vstat->sigrdataset, 0, NULL);
|
||||
val->sigrdataset, 0, NULL);
|
||||
}
|
||||
if (wnode != NULL) {
|
||||
dns_db_detachnode(fctx->cache, &wnode);
|
||||
@@ -5796,7 +5789,7 @@ answer_response:
|
||||
|
||||
if (hresp != NULL) {
|
||||
/*
|
||||
* Negative results must be indicated in vstat->result.
|
||||
* Negative results must be indicated in val->result.
|
||||
*/
|
||||
INSIST(hresp->rdataset != NULL);
|
||||
if (dns_rdataset_isassociated(hresp->rdataset) &&
|
||||
@@ -5807,7 +5800,7 @@ answer_response:
|
||||
}
|
||||
|
||||
hresp->result = eresult;
|
||||
dns_name_copy(vstat->name, hresp->foundname);
|
||||
dns_name_copy(val->name, hresp->foundname);
|
||||
dns_db_attach(fctx->cache, &hresp->db);
|
||||
dns_db_transfernode(fctx->cache, &node, &hresp->node);
|
||||
clone_results(fctx);
|
||||
@@ -6320,8 +6313,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_message_t *message,
|
||||
result = valcreate(
|
||||
fctx, message, addrinfo, name,
|
||||
rdataset->type, rdataset,
|
||||
sigrdataset, valoptions,
|
||||
fctx->loop);
|
||||
sigrdataset, valoptions);
|
||||
}
|
||||
} else if (CHAINING(rdataset)) {
|
||||
if (rdataset->type == dns_rdatatype_cname) {
|
||||
@@ -6429,8 +6421,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_message_t *message,
|
||||
}
|
||||
|
||||
result = valcreate(fctx, message, addrinfo, name, vtype,
|
||||
valrdataset, valsigrdataset, valoptions,
|
||||
fctx->loop);
|
||||
valrdataset, valsigrdataset, valoptions);
|
||||
}
|
||||
|
||||
if (result == ISC_R_SUCCESS && have_answer) {
|
||||
@@ -6652,7 +6643,7 @@ ncache_message(fetchctx_t *fctx, dns_message_t *message,
|
||||
* Do negative response validation.
|
||||
*/
|
||||
result = valcreate(fctx, message, addrinfo, name, fctx->type,
|
||||
NULL, NULL, valoptions, fctx->loop);
|
||||
NULL, NULL, valoptions);
|
||||
/*
|
||||
* If validation is necessary, return now. Otherwise
|
||||
* continue to process the message, letting the
|
||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user