Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Knot DNS
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
24
Issues
24
List
Boards
Labels
Service Desk
Milestones
Merge Requests
18
Merge Requests
18
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Knot projects
Knot DNS
Commits
dde98863
Commit
dde98863
authored
Jun 21, 2016
by
Vitezslav Kriz
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
zone-size-limit: axfr, ixfr transfer size limit
parent
52385c1a
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
186 additions
and
5 deletions
+186
-5
src/knot/conf/scheme.c
src/knot/conf/scheme.c
+1
-0
src/knot/conf/scheme.h
src/knot/conf/scheme.h
+1
-0
src/knot/nameserver/axfr.c
src/knot/nameserver/axfr.c
+24
-1
src/knot/nameserver/axfr.h
src/knot/nameserver/axfr.h
+2
-0
src/knot/nameserver/ixfr.c
src/knot/nameserver/ixfr.c
+45
-4
src/knot/zone/contents.h
src/knot/zone/contents.h
+1
-0
src/knot/zone/semantic-check.c
src/knot/zone/semantic-check.c
+18
-0
src/libknot/rrset.c
src/libknot/rrset.c
+19
-0
src/libknot/rrset.h
src/libknot/rrset.h
+2
-0
tests-extra/tests/ixfr/transfer_size/data/example.com.zone
tests-extra/tests/ixfr/transfer_size/data/example.com.zone
+8
-0
tests-extra/tests/ixfr/transfer_size/data/example.com.zone.1
tests-extra/tests/ixfr/transfer_size/data/example.com.zone.1
+10
-0
tests-extra/tests/ixfr/transfer_size/data/example.com.zone.2
tests-extra/tests/ixfr/transfer_size/data/example.com.zone.2
+10
-0
tests-extra/tests/ixfr/transfer_size/test.py
tests-extra/tests/ixfr/transfer_size/test.py
+42
-0
tests-extra/tools/dnstest/server.py
tests-extra/tools/dnstest/server.py
+3
-0
No files found.
src/knot/conf/scheme.c
View file @
dde98863
...
...
@@ -205,6 +205,7 @@ static const yp_item_t desc_remote[] = {
{ C_ZONEFILE_SYNC, YP_TINT, YP_VINT = { -1, INT32_MAX, 0, YP_STIME } }, \
{ C_IXFR_DIFF, YP_TBOOL, YP_VNONE }, \
{ C_MAX_JOURNAL_SIZE, YP_TINT, YP_VINT = { 0, INT64_MAX, INT64_MAX, YP_SSIZE } }, \
{ C_MAX_ZONE_SIZE, YP_TINT, YP_VINT = { 0, INT64_MAX, INT64_MAX, YP_SSIZE } }, \
{ C_KASP_DB, YP_TSTR, YP_VSTR = { "keys" } }, \
{ C_DNSSEC_SIGNING, YP_TBOOL, YP_VNONE }, \
{ C_DNSSEC_POLICY, YP_TREF, YP_VREF = { C_POLICY }, YP_FNONE, { check_ref_dflt } }, \
...
...
src/knot/conf/scheme.h
View file @
dde98863
...
...
@@ -63,6 +63,7 @@
#define C_MAX_JOURNAL_SIZE "\x10""max-journal-size"
#define C_MAX_TCP_CLIENTS "\x0F""max-tcp-clients"
#define C_MAX_UDP_PAYLOAD "\x0F""max-udp-payload"
#define C_MAX_ZONE_SIZE "\x0D""max-zone-size"
#define C_MODULE "\x06""module"
#define C_NOTIFY "\x06""notify"
#define C_NSEC3 "\x05""nsec3"
...
...
src/knot/nameserver/axfr.c
View file @
dde98863
...
...
@@ -20,6 +20,7 @@
#include "contrib/print.h"
#include "contrib/sockaddr.h"
#include "knot/common/log.h"
#include "knot/conf/conf.h"
#include "knot/nameserver/axfr.h"
#include "knot/nameserver/internet.h"
#include "knot/zone/zonefile.h"
...
...
@@ -265,6 +266,7 @@ static void axfr_answer_cleanup(struct answer_data *data)
struct
xfr_proc
*
proc
=
data
->
ext
;
if
(
proc
)
{
zone_contents_deep_free
(
&
proc
->
contents
);
conf_free
(
proc
->
conf
);
mm_free
(
data
->
mm
,
proc
);
data
->
ext
=
NULL
;
}
...
...
@@ -281,16 +283,25 @@ static int axfr_answer_init(struct answer_data *data)
return
KNOT_ENOMEM
;
}
conf_t
*
conf
;
int
ret
=
conf_clone
(
&
conf
);
if
(
ret
!=
KNOT_EOK
)
{
zone_contents_deep_free
(
&
new_contents
);
return
ret
;
}
/* Create new processing context. */
struct
xfr_proc
*
proc
=
mm_alloc
(
data
->
mm
,
sizeof
(
struct
xfr_proc
));
if
(
proc
==
NULL
)
{
zone_contents_deep_free
(
&
new_contents
);
conf_free
(
conf
);
return
KNOT_ENOMEM
;
}
memset
(
proc
,
0
,
sizeof
(
struct
xfr_proc
));
proc
->
contents
=
new_contents
;
gettimeofday
(
&
proc
->
tstamp
,
NULL
);
proc
->
conf
=
conf
;
/* Set up cleanup callback. */
data
->
ext
=
proc
;
...
...
@@ -360,6 +371,10 @@ static int axfr_answer_packet(knot_pkt_t *pkt, struct xfr_proc *proc)
proc
->
npkts
+=
1
;
proc
->
nbytes
+=
pkt
->
size
;
conf_val_t
val
=
conf_zone_get
(
proc
->
conf
,
C_MAX_ZONE_SIZE
,
proc
->
contents
->
apex
->
owner
);
int64_t
size_limit
=
conf_int
(
&
val
);
/* Init zone creator. */
zcreator_t
zc
=
{.
z
=
proc
->
contents
,
.
master
=
false
,
.
ret
=
KNOT_EOK
};
...
...
@@ -368,13 +383,21 @@ static int axfr_answer_packet(knot_pkt_t *pkt, struct xfr_proc *proc)
for
(
uint16_t
i
=
0
;
i
<
answer
->
count
;
++
i
)
{
if
(
answer_rr
[
i
].
type
==
KNOT_RRTYPE_SOA
&&
node_rrtype_exists
(
zc
.
z
->
apex
,
KNOT_RRTYPE_SOA
))
{
return
KNOT_STATE_DONE
;
log_zone_debug
(
proc
->
contents
->
apex
->
owner
,
"size: %zu"
,
proc
->
contents
->
size
);
return
KNOT_STATE_DONE
;
}
else
{
int
ret
=
zcreator_step
(
&
zc
,
&
answer_rr
[
i
]);
if
(
ret
!=
KNOT_EOK
)
{
return
KNOT_STATE_FAIL
;
}
}
proc
->
contents
->
size
+=
knot_rrset_size
(
&
answer_rr
[
i
]);
if
(
proc
->
contents
->
size
>
size_limit
)
{
log_zone_warning
(
proc
->
contents
->
apex
->
owner
,
"AXFR, incoming, zone size exceeded, "
"limit %ld"
,
size_limit
);
return
KNOT_STATE_FAIL
;
}
}
return
KNOT_STATE_CONSUME
;
...
...
src/knot/nameserver/axfr.h
View file @
dde98863
...
...
@@ -25,6 +25,7 @@
#pragma once
#include "libknot/packet/pkt.h"
#include "knot/conf/conf.h"
#include "knot/nameserver/log.h"
#include "knot/query/query.h"
#include "knot/nameserver/process_query.h"
...
...
@@ -60,6 +61,7 @@ struct xfr_proc {
unsigned
nbytes
;
/* Bytes processed. */
struct
timeval
tstamp
;
/* Start time. */
zone_contents_t
*
contents
;
/* Processed zone. */
conf_t
*
conf
;
};
/*! \brief Generic transfer processing (reused for IXFR).
...
...
src/knot/nameserver/ixfr.c
View file @
dde98863
...
...
@@ -50,6 +50,8 @@ struct ixfr_proc {
knot_rrset_t
*
final_soa
;
/* First SOA received via IXFR. */
list_t
changesets
;
/* Processed changesets. */
size_t
change_count
;
/* Count of changesets received. */
size_t
add_size
;
size_t
del_size
;
zone_t
*
zone
;
/* Modified zone - for journal access. */
knot_mm_t
*
mm
;
/* Memory context for RR allocations. */
struct
query_data
*
qdata
;
...
...
@@ -338,6 +340,7 @@ static void ixfrin_cleanup(struct answer_data *data)
if
(
proc
)
{
changesets_free
(
&
proc
->
changesets
);
knot_rrset_free
(
&
proc
->
final_soa
,
proc
->
mm
);
conf_free
(
proc
->
proc
.
conf
);
mm_free
(
data
->
mm
,
proc
);
data
->
ext
=
NULL
;
}
...
...
@@ -346,12 +349,21 @@ static void ixfrin_cleanup(struct answer_data *data)
/*! \brief Initializes IXFR-in processing context. */
static
int
ixfrin_answer_init
(
struct
answer_data
*
data
)
{
conf_t
*
conf
;
int
ret
=
conf_clone
(
&
conf
);
if
(
ret
!=
KNOT_EOK
)
{
return
ret
;
}
struct
ixfr_proc
*
proc
=
mm_alloc
(
data
->
mm
,
sizeof
(
struct
ixfr_proc
));
if
(
proc
==
NULL
)
{
conf_free
(
conf
);
return
KNOT_ENOMEM
;
}
memset
(
proc
,
0
,
sizeof
(
struct
ixfr_proc
));
gettimeofday
(
&
proc
->
proc
.
tstamp
,
NULL
);
proc
->
proc
.
conf
=
conf
;
init_list
(
&
proc
->
changesets
);
...
...
@@ -543,17 +555,34 @@ static int ixfrin_step(const knot_rrset_t *rr, struct ixfr_proc *proc)
proc
->
state
=
ixfrin_next_state
(
proc
,
rr
);
changeset_t
*
change
=
TAIL
(
proc
->
changesets
);
int
ret
;
switch
(
proc
->
state
)
{
case
IXFR_START
:
return
solve_start
(
rr
,
proc
);
case
IXFR_SOA_DEL
:
return
solve_soa_del
(
rr
,
proc
);
ret
=
solve_soa_del
(
rr
,
proc
);
if
(
ret
==
KNOT_EOK
)
{
proc
->
del_size
+=
knot_rrset_size
(
rr
);
}
return
ret
;
case
IXFR_DEL
:
return
solve_del
(
rr
,
change
,
proc
->
mm
);
ret
=
solve_del
(
rr
,
change
,
proc
->
mm
);
if
(
ret
==
KNOT_EOK
)
{
proc
->
del_size
+=
knot_rrset_size
(
rr
);
}
return
ret
;
case
IXFR_SOA_ADD
:
return
solve_soa_add
(
rr
,
change
,
proc
->
mm
);
ret
=
solve_soa_add
(
rr
,
change
,
proc
->
mm
);
if
(
ret
==
KNOT_EOK
)
{
proc
->
add_size
+=
knot_rrset_size
(
rr
);
}
return
ret
;
case
IXFR_ADD
:
return
solve_add
(
rr
,
change
,
proc
->
mm
);
ret
=
solve_add
(
rr
,
change
,
proc
->
mm
);
if
(
ret
==
KNOT_EOK
)
{
proc
->
add_size
+=
knot_rrset_size
(
rr
);
}
return
ret
;
case
IXFR_DONE
:
return
KNOT_EOK
;
default:
...
...
@@ -589,6 +618,11 @@ static int process_ixfrin_packet(knot_pkt_t *pkt, struct answer_data *adata)
ixfr
->
proc
.
npkts
+=
1
;
ixfr
->
proc
.
nbytes
+=
pkt
->
size
;
conf_val_t
val
=
conf_zone_get
(
ixfr
->
proc
.
conf
,
C_MAX_ZONE_SIZE
,
ixfr
->
zone
->
name
);
const
int64_t
size_limit
=
conf_int
(
&
val
);
const
size_t
zone_size
=
ixfr
->
zone
->
contents
->
size
;
// Process RRs in the message.
const
knot_pktsection_t
*
answer
=
knot_pkt_section
(
pkt
,
KNOT_ANSWER
);
for
(
uint16_t
i
=
0
;
i
<
answer
->
count
;
++
i
)
{
...
...
@@ -612,6 +646,13 @@ static int process_ixfrin_packet(knot_pkt_t *pkt, struct answer_data *adata)
// Transfer done, do not consume more RRs.
return
KNOT_STATE_DONE
;
}
if
((
ixfr
->
add_size
+
ixfr
->
del_size
>
2
*
size_limit
)
||
(
zone_size
+
ixfr
->
add_size
-
ixfr
->
del_size
>
size_limit
))
{
IXFRIN_LOG
(
LOG_WARNING
,
"zone size exceeded, limit %ld"
,
size_limit
);
return
KNOT_STATE_FAIL
;
}
}
return
KNOT_STATE_CONSUME
;
...
...
src/knot/zone/contents.h
View file @
dde98863
...
...
@@ -41,6 +41,7 @@ typedef struct zone_contents {
zone_tree_t
*
nsec3_nodes
;
dnssec_nsec3_params_t
nsec3_params
;
size_t
size
;
}
zone_contents_t
;
/*!
...
...
src/knot/zone/semantic-check.c
View file @
dde98863
...
...
@@ -144,6 +144,7 @@ static int check_rrsig(const zone_node_t *node, semchecks_data_t *data);
static
int
check_signed_rrsig
(
const
zone_node_t
*
node
,
semchecks_data_t
*
data
);
static
int
check_nsec_bitmap
(
const
zone_node_t
*
node
,
semchecks_data_t
*
data
);
static
int
check_nsec3_presence
(
const
zone_node_t
*
node
,
semchecks_data_t
*
data
);
static
int
measure_size
(
const
zone_node_t
*
node
,
semchecks_data_t
*
data
);
struct
check_function
{
int
(
*
function
)(
const
zone_node_t
*
,
semchecks_data_t
*
);
...
...
@@ -162,11 +163,24 @@ static const struct check_function CHECK_FUNCTIONS[] = {
{
check_nsec3_presence
,
NSEC3
},
{
check_nsec3_opt_out
,
NSEC3
},
{
check_nsec_bitmap
,
NSEC
|
NSEC3
},
{
measure_size
,
MANDATORY
}
};
static
const
int
CHECK_FUNCTIONS_LEN
=
sizeof
(
CHECK_FUNCTIONS
)
/
sizeof
(
struct
check_function
);
static
int
measure_size
(
const
zone_node_t
*
node
,
semchecks_data_t
*
data
){
int
rrset_count
=
node
->
rrset_count
;
for
(
int
i
=
0
;
i
<
rrset_count
;
i
++
)
{
knot_rrset_t
rrset
=
node_rrset_at
(
node
,
i
);
data
->
zone
->
size
+=
knot_rrset_size
(
&
rrset
);
}
return
KNOT_EOK
;
}
/*!
* \brief Check whether DNSKEY rdata are valid.
*
...
...
@@ -916,6 +930,8 @@ int zone_do_sem_checks(zone_contents_t *zone, bool optional,
return
KNOT_EINVAL
;
}
zone
->
size
=
0
;
semchecks_data_t
data
=
{
.
handler
=
handler
,
.
zone
=
zone
,
...
...
@@ -937,6 +953,8 @@ int zone_do_sem_checks(zone_contents_t *zone, bool optional,
int
ret
=
zone_contents_tree_apply_inorder
(
zone
,
do_checks_in_tree
,
&
data
);
log_zone_debug
(
zone
->
apex
->
owner
,
"semcheck: size of zone: %zu"
,
zone
->
size
);
if
(
ret
!=
KNOT_EOK
)
{
return
ret
;
}
...
...
src/libknot/rrset.c
View file @
dde98863
...
...
@@ -254,3 +254,22 @@ int knot_rrset_rr_to_canonical(knot_rrset_t *rrset)
return
KNOT_EOK
;
}
_public_
size_t
knot_rrset_size
(
const
knot_rrset_t
*
rrset
)
{
if
(
rrset
==
NULL
)
{
return
0
;
}
uint16_t
rr_count
=
rrset
->
rrs
.
rr_count
;
size_t
total_size
=
knot_dname_size
(
rrset
->
owner
)
*
rr_count
;
for
(
size_t
i
=
0
;
i
<
rr_count
;
++
i
)
{
const
knot_rdata_t
*
rr
=
knot_rdataset_at
(
&
rrset
->
rrs
,
i
);
assert
(
rr
);
total_size
+=
knot_rdata_rdlen
(
rr
)
+
10
;
}
return
total_size
;
}
src/libknot/rrset.h
View file @
dde98863
...
...
@@ -194,4 +194,6 @@ bool knot_rrset_is_nsec3rel(const knot_rrset_t *rr);
*/
int
knot_rrset_rr_to_canonical
(
knot_rrset_t
*
rrset
);
size_t
knot_rrset_size
(
const
knot_rrset_t
*
rrset
);
/*! @} */
tests-extra/tests/ixfr/transfer_size/data/example.com.zone
0 → 100644
View file @
dde98863
$ORIGIN example.com.
$TTL 3600
@ SOA dns1 hostmaster 2010111200 10800 3600 1209600 7200
NS dns1
dns1 A 192.0.2.1
A 192.0.2.2
tests-extra/tests/ixfr/transfer_size/data/example.com.zone.1
0 → 100644
View file @
dde98863
$ORIGIN example.com.
$TTL 3600
@ SOA dns1 hostmaster 2010111201 10800 3600 1209600 7200
NS dns1
dns1 A 192.0.2.1
A 192.0.2.2
test TXT "passed"
tests-extra/tests/ixfr/transfer_size/data/example.com.zone.2
0 → 100644
View file @
dde98863
$ORIGIN example.com.
$TTL 3600
@ SOA dns1 hostmaster 2010111201 10800 3600 1209600 7200
NS dns1
dns1 A 192.0.2.1
A 192.0.2.2
test TXT "FAILED. This zone is larger than limit. More text: Lorem impsum dolor sit a met."
tests-extra/tests/ixfr/transfer_size/test.py
0 → 100644
View file @
dde98863
#!/usr/bin/env python3
'''Test for IXFR from Knot to Knot'''
from
dnstest.test
import
Test
t
=
Test
()
master1
=
t
.
server
(
"knot"
)
master2
=
t
.
server
(
"knot"
)
slave
=
t
.
server
(
"knot"
)
zone
=
t
.
zone
(
"example.com."
,
storage
=
"."
)
slave
.
zone_size_limit
=
230
t
.
link
(
zone
,
master1
,
slave
,
ixfr
=
True
)
t
.
link
(
zone
,
master2
,
slave
,
ixfr
=
True
)
t
.
start
()
# Wait for zones.
serial
=
master1
.
zone_wait
(
zone
)
slave
.
zone_wait
(
zone
)
# Update master file with the record (new SOA serial).
master1
.
update_zonefile
(
zone
,
version
=
2
)
master1
.
reload
()
# Wait for zones and compare them.
master1
.
zone_wait
(
zone
,
serial
)
t
.
sleep
(
10
)
master2
.
update_zonefile
(
zone
,
version
=
1
)
# smaller zone
master2
.
reload
()
slave
.
zone_wait
(
zone
,
serial
)
resp
=
slave
.
dig
(
"test.example.com."
,
"TXT"
)
resp
.
check
(
"passed"
)
#t.xfr_diff(master, slave, zone)
t
.
end
()
tests-extra/tools/dnstest/server.py
View file @
dde98863
...
...
@@ -847,6 +847,7 @@ class Knot(Server):
self
.
daemon_bin
=
params
.
knot_bin
self
.
control_bin
=
params
.
knot_ctl
self
.
inquirer
=
dnstest
.
inquirer
.
Inquirer
()
self
.
zone_size_limit
=
None
@
property
def
keydir
(
self
):
...
...
@@ -1033,6 +1034,8 @@ class Knot(Server):
modules
+=
", "
modules
+=
module
.
get_conf_ref
()
s
.
item
(
"global-module"
,
"[%s]"
%
modules
)
if
self
.
zone_size_limit
:
s
.
item
(
"max-zone-size"
,
self
.
zone_size_limit
)
s
.
end
()
s
.
begin
(
"zone"
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment