@@ -10,6 +10,7 @@ use crate::{Implementation, Result};
10
10
pub struct Resolver {
11
11
container : Container ,
12
12
child : Child ,
13
+ implementation : Implementation ,
13
14
}
14
15
15
16
impl Resolver {
@@ -26,8 +27,6 @@ impl Resolver {
26
27
trust_anchor : & TrustAnchor ,
27
28
network : & Network ,
28
29
) -> Result < Self > {
29
- const TRUST_ANCHOR_FILE : & str = "/etc/trusted-key.key" ;
30
-
31
30
assert ! (
32
31
!roots. is_empty( ) ,
33
32
"must configure at least one local root server"
@@ -43,6 +42,15 @@ impl Resolver {
43
42
44
43
let use_dnssec = !trust_anchor. is_empty ( ) ;
45
44
match implementation {
45
+ Implementation :: Bind => {
46
+ container. cp ( "/etc/bind/root.hints" , & hints) ?;
47
+
48
+ container. cp (
49
+ "/etc/bind/named.conf" ,
50
+ & named_conf ( use_dnssec, network. netmask ( ) ) ,
51
+ ) ?;
52
+ }
53
+
46
54
Implementation :: Unbound => {
47
55
container. cp ( "/etc/unbound/root.hints" , & hints) ?;
48
56
@@ -62,16 +70,33 @@ impl Resolver {
62
70
}
63
71
64
72
if use_dnssec {
65
- container. cp ( TRUST_ANCHOR_FILE , & trust_anchor. to_string ( ) ) ?;
73
+ let path = if implementation. is_bind ( ) {
74
+ "/etc/bind/bind.keys"
75
+ } else {
76
+ "/etc/trusted-key.key"
77
+ } ;
78
+
79
+ let contents = if implementation. is_bind ( ) {
80
+ trust_anchor. delv ( )
81
+ } else {
82
+ trust_anchor. to_string ( )
83
+ } ;
84
+
85
+ container. cp ( path, & contents) ?;
66
86
}
67
87
68
88
let command: & [ _ ] = match implementation {
89
+ Implementation :: Bind => & [ "named" , "-g" , "-d5" ] ,
69
90
Implementation :: Unbound => & [ "unbound" , "-d" ] ,
70
91
Implementation :: Hickory { .. } => & [ "hickory-dns" , "-d" ] ,
71
92
} ;
72
93
let child = container. spawn ( command) ?;
73
94
74
- Ok ( Self { child, container } )
95
+ Ok ( Self {
96
+ child,
97
+ container,
98
+ implementation : implementation. clone ( ) ,
99
+ } )
75
100
}
76
101
77
102
pub fn eavesdrop ( & self ) -> Result < Tshark > {
@@ -88,7 +113,11 @@ impl Resolver {
88
113
89
114
/// gracefully terminates the name server collecting all logs
90
115
pub fn terminate ( self ) -> Result < String > {
91
- let pidfile = "/run/unbound.pid" ;
116
+ let pidfile = match self . implementation {
117
+ Implementation :: Bind => "/tmp/named.pid" ,
118
+ Implementation :: Unbound => "/run/unbound.pid" ,
119
+ Implementation :: Hickory ( ..) => unimplemented ! ( ) ,
120
+ } ;
92
121
let kill = format ! (
93
122
"test -f {pidfile} || sleep 1
94
123
kill -TERM $(cat {pidfile})"
@@ -108,6 +137,10 @@ kill -TERM $(cat {pidfile})"
108
137
}
109
138
}
110
139
140
+ fn named_conf ( use_dnssec : bool , netmask : & str ) -> String {
141
+ minijinja:: render!( include_str!( "templates/named.resolver.conf.jinja" ) , use_dnssec => use_dnssec, netmask => netmask)
142
+ }
143
+
111
144
fn unbound_conf ( use_dnssec : bool , netmask : & str ) -> String {
112
145
minijinja:: render!( include_str!( "templates/unbound.conf.jinja" ) , use_dnssec => use_dnssec, netmask => netmask)
113
146
}
@@ -123,7 +156,7 @@ mod tests {
123
156
use super :: * ;
124
157
125
158
#[ test]
126
- fn terminate_works ( ) -> Result < ( ) > {
159
+ fn terminate_unbound_works ( ) -> Result < ( ) > {
127
160
let network = Network :: new ( ) ?;
128
161
let ns = NameServer :: new ( & Implementation :: Unbound , FQDN :: ROOT , & network) ?. start ( ) ?;
129
162
let resolver = Resolver :: start (
@@ -139,4 +172,22 @@ mod tests {
139
172
140
173
Ok ( ( ) )
141
174
}
175
+
176
+ #[ test]
177
+ fn terminate_bind_works ( ) -> Result < ( ) > {
178
+ let network = Network :: new ( ) ?;
179
+ let ns = NameServer :: new ( & Implementation :: Unbound , FQDN :: ROOT , & network) ?. start ( ) ?;
180
+ let resolver = Resolver :: start (
181
+ & Implementation :: Bind ,
182
+ & [ Root :: new ( ns. fqdn ( ) . clone ( ) , ns. ipv4_addr ( ) ) ] ,
183
+ & TrustAnchor :: empty ( ) ,
184
+ & network,
185
+ ) ?;
186
+ let logs = resolver. terminate ( ) ?;
187
+
188
+ eprintln ! ( "{logs}" ) ;
189
+ assert ! ( logs. contains( "starting BIND" ) ) ;
190
+
191
+ Ok ( ( ) )
192
+ }
142
193
}
0 commit comments