-
Notifications
You must be signed in to change notification settings - Fork 1
/
ods-dswatcher
executable file
·634 lines (533 loc) · 17.2 KB
/
ods-dswatcher
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
#!/usr/bin/env bash
# $Id: ods-dswatcher 105408 2019-08-09 12:40:35Z cgielen $
# $URL: https://svn.uvt.nl/its-unix/systems/metagross/usr/local/sbin/ods-dswatcher $
#
# Check if new DSes have been published in DNS and activate them, also deactives old DSes that have been removed.
#
#
# Copyright 2013-2018 Casper Gielen
# Written for Tilburg University
# License: GPLv2 or later
#
# TODO
# - match on CKAID instead of keytag
# - better deal with the difference between failure of DNS and a zone without DNSKEYS
# - support phase-in / phase-out of DNSKEYS
# - support zones without DNSKEYS
#set -x
# Default options for dig
# This script runs often so don't worry about incidental failed queries or long timeouts.
# Zones with temporary failures will be picked-up on the next run.
dig_options="+timeout=2 +tries=2"
# DIG: if not in path, specify full path to dig
DIG="/usr/bin/dig $dig_options"
# DIGP: DIG used for finding parent info
DIGP="/usr/bin/dig $dig_options"
logfile=/var/log/dnssec/ods-dswatcher.log
# requires shunit2 to be installed
USE_SHUNIT=false
usage() {
echo "usage: $0 [--activate|--force|--quiet|--help] <zone|...>"
echo "Check if all DS-records are available through DNS and (optionally) activate the key."
echo "--help Display this help text."
echo "--activate Activate the key if the DS is found."
echo "--force Force activation of keys that are not available (implies --activate)."
echo "--quiet Surpress non-critical output (loglevel = 1)."
echo "--verbose More verbose output (loglevel = 4)."
echo "-d|--debug Detailed debug output (loglevel = 9)."
echo "--all Apply to all zones with outstanding DSes."
echo "--really-all Apply to all zones, required or not."
echo "--test Run unit tests."
exit -1
}
# stuur naar logfile en eventueel de console
# $1 = loglevel
log() {
loglevel="$1"
[ $loglevel -gt $LOGLEVEL ] && return
shift
echo "$*"
[ $loglevel -gt $LOGLEVEL ] && [ $loglevel -gt 3 ] && return # kritiek berichten altijd loggen
echo "$(date) $*" >> $logfile
}
# strip overbodige output
nosql() {
egrep -v '^MySQL database'
}
# strip leading and trailing whitespace
trim() {
sed 's/^[[:space:]]*//; s/[[:space:]]*$//; /^$/d;'
}
# print stdin as a single line (removing linebreaks and stripping whitespace)
row() {
tr '\n' ' ' | trim
}
# get OpenDNSSEC version
ods_version() {
/usr/sbin/ods-enforcerd -V|awk '/^opendnssec version/ { print $3 }'
}
# use dig to get keytags of the DS'es published for a zone
# $1 = zone to look up
# $2 = outputfile '$dns' for all keytags
# return code: exit code of last call to dig (0 = success)
get_keytags_from_dns() {
zone="$1"
dns="$2"
echo > $dns
# Figure out what the nameservers of the parent domain are
# so we can avoid using a resolver that might cache old information.
# There must be a better way. (? Use dig/drill in Trace mode and just look at the last entry???)
# Perhaps check all masters?
parent=${zone#*.}
server=$($DIGP +short -t NS $parent| sort -R | head -n 1; exit ${PIPESTATUS[1]})
ret=$?
if [ "$ret" != 0 ] || [ -z "$parent" ] || [ -z "$server" ]; then
log 4 "$zone: error: unable to determine authorative DNS-server. (parent domain='$parent', DNS-server='$server')"
return $ret
fi
log 8 "Searching .$parent (NS: $server) for $zone"
# Keytags that can be retrieved from DNS
# dig: 39269 8 2 9EC50E7BBCC4095355A776D6183773197C05F320FDDE87E513022DB9 6A1E2F48
answer=$($DIG +adflag +aaonly +short -t DS $zone @$server)
ret=$?
log 9 "dig raw: $answer"
if [ "$ret" != 0 ]; then
log 4 "$zone: error: DNS-server='$server': $answer)"
return $ret
fi
echo "$answer" | cut -d ' ' -f 1 | trim | sort -u > $dns
# return status of dig
return $ret
}
# Get the keytags that ODS knows about.
# $1 = zone to look up
# $2 = outputfile '$ods' for all keytags
# $3 = outputfile '$w4s' for waiting for ds-seen
# $4 = outputfile '$w4g' for waiting for ds-gone
get_keytags_from_ods() {
zone="$1"
ods="$2"
w4s="$3"
w4g="$4"
# create cache of keys known to ODS
if [ ! -s "$keylist" ] ; then
# ods-enforcer:tilt.nl;KSK;ready;waiting for ds-seen;2048;8;e59a9b5a16a393f969f4ec6d652db27d;LocalHSM;49087
$ENFORCER key list $ods_verbose --keytype KSK 2>/dev/null \
| sort 2>/dev/null > $keylist
#log 9 "ods keylist: $(cat $keylist)"
fi
awk -F "$seperator" -v zone=$zone -v keytagcol=$keytagcol -v transcol=$transcol '$1 == zone {print $keytagcol}' < $keylist | sort > $ods # All keys known by ODS
awk -F "$seperator" -v zone=$zone -v keytagcol=$keytagcol -v transcol=$transcol '$1 == zone && $transcol == "waiting for ds-seen" {print $keytagcol}' < $keylist | sort > $w4s # Keys in the state "waiting for DS-SEEN"
awk -F "$seperator" -v zone=$zone -v keytagcol=$keytagcol -v transcol=$transcol '$1 == zone && $transcol == "waiting for ds-gone" {print $keytagcol}' < $keylist | sort > $w4g # Keys in the state "Waiting for DS-GONE"
}
# Compare the keytags from ODS to those found in DNS
# $1 = inputfile '$dns'
# $2 = inputfile '$ods'
# $3 = inputfile '$w4s'
# $4 = inputfile '$w4g'
# $5 = outputfile '$seen'
# $6 = outputfile '$notseen'
# $7 = outputfile '$gone'
# $8 = outputfile '$notgone'
# $9 = outputfile '$unknown'
compare_keytags() {
dns="$1"
ods="$2"
w4s="$3"
w4g="$4"
comm -12 $w4s $dns | trim > $seen # new in DNS
comm -23 $w4s $dns | trim > $notseen # not yet in DNS
comm -23 $w4g $dns | trim > $gone # gone from DNS
comm -12 $w4g $dns | trim > $notgone # still in DNS
comm -13 $ods $dns | trim > $unknown # keys found in DNS that are unknown to DODS
}
# Notify ODS of keys to activate or deactivate
# $1 = zone to operate on
# $2 = inputfile '$seen' - keys that recently appeared in DNS
# $3 = inputfile '$gone' - keys that are no longer in DNS
notify_ods() {
zone="$1"
seen="$2"
gone="$3"
case $zone in "uvt.nl")
log 2 "$zone: De zone $zone is speciaal, doe deze MET DE HAND!"
log 2 "bv: ods-enforcer key ds-seen --zone $zone --keytag ..."
return
esac
# activate newly published keys
for keytag in $(cat $seen); do
output=$($ENFORCER key ds-seen --zone $zone --keytag $keytag 2>&1 | nosql)
log 4 "$zone: $output"
log 4 "$zone: Key $keytag activated."
done
# deactive keys that have geen away
for keytag in $(cat $gone); do
output=$($ENFORCER key ds-gone --zone $zone --keytag $keytag 2>&1 | nosql)
log 4 "$zone: $output"
log 4 "$zone: Key $keytag deactivated."
done
}
# (De)activate keys by force. Do not check if it is ok to (de)activate, just do it.
# $1 = zone to operate on
# $2 = inputfile '$w4s' - waiting for seen
# $3 = inputfile '$w4g' - waiting for gone
# $4 = outputfile '$seen' - keys that can be activated
# $5 = outputfile '$gone' - keys that can be deactivated
force_activate() {
zone="$1"
w4s="$2"
w4g="$3"
seen="$4"
gone="$5"
if [ -s "$w4s" ]; then
cp $w4s $seen
log 3 "$zone: warning: forced activation of key(s) $(cat $seen)"
fi
if [ -s "$w4g" ]; then
cp $w4g $gone
log 3 "$zone: warning: forced removal of key(s) $(cat $gone)"
fi
}
print_debug() {
log 8 "In DNS: '$(cat $dns | row)'"
log 8 "In ODS: '$(cat $ods | row)'"
log 8 "Waiting for ds-seen: '$(cat $w4s | row)'"
log 8 "Waiting for ds-gone: '$(cat $w4g | row)'"
log 8 "Seen: '$(cat $seen | row)'"
log 8 "Not seen: '$(cat $notseen | row)'"
log 8 "Gone: '$(cat $gone | row)'"
log 8 "Not gone: '$(cat $notgone | row)'"
log 8 "Unknown: '$(cat $unknown | row)'"
}
digTEST() {
# dig +adflag +aaonly +short -t DS uvt.nl @ns1.dns.nl
cat<<EOF
21035 8 2 FBA2A1128B51A10B7819E02083628FF3EB5EA070CFD0C2D28FCCD24C 8029D6C1
EOF
}
digTEST2() {
cat <<EOF
33827 8 2 5B9FB9A893DAA05AC7B95C2265C2CD926A576E89A3E8498CD541EF4E 73D81E54
30701 8 2 D53C38F3779438E59A5B8CE8744D6E34622BA2D9C4EADF1E270F8F36 EA667C9E
49351 8 1 789265F323AF2F4869C9A14D728C0E99AA199382
49351 8 2 65DD98874A16D4425ECC76C11B61DA52FA1F21CB2954E6ECC682D2A0 50CB20C6
EOF
}
enforcerTEST() {
cat <<EOF
tilt.nl;KSK;retire;waiting for ds-gone;2048;8;78ee5d99516c9bc234993204568c0b80;LocalHSM;48134
tilt.nl;KSK;retire;2018-04-27 07:16:35;2048;8;1ce5187e3349097ffaf6557ef67bbc87;LocalHSM;60559
tilt.nl;KSK;ready;waiting for ds-seen;2048;8;e59a9b5a16a393f969f4ec6d652db27d;LocalHSM;49087
key list completed in 0 seconds.
EOF
}
digTEST3() {
# dig +adflag +aaonly +short -t DS mijnuvt.nl @ns1.dns.nl
cat <<EOF
54321 8 2 DS236656A65B454C664E432D131F343A546B65C56D53E12F124532EF 12345678
21892 8 2 DA9882633A4BEC7287AFC2029B338CAAD742B8ED7D47654CA0D482EF E4665C63
35389 8 2 D8A3E30DC79C06DC29DEE550934D21EBD6C485F6F376B79512661A17 54E65BE5
EOF
}
enforcerTEST3() {
# ods-enforcer key list -v -p --zone mijnuvt.nl --keytype KSK
cat <<EOF
mijnuvt.nl;KSK;retire;waiting for ds-gone;2048;8;4f0fcf68d8468c2a30233fa945165fff;LocalHSM;35389
mijnuvt.nl;KSK;ready;waiting for ds-seen;2048;8;f490c0e1ec0e351001fc4874d229c1af;LocalHSM;21892
key list completed in 0 seconds.
EOF
}
digTEST4() {
# /usr/sbin/ods-enforcer key list -v -p --zone eurovalues.be --keytype KSK
cat <<EOF
27032 8 1 03D11D067EBC9F666A7A9E34D4A29CB1D12189F7
27032 8 2 0805BF0D399876D132082F3936BDD6C2097F4AC8450626DFE9AA89DC A361046B
60067 8 2 45DB8DE324FF326F7D95D226ACE1F74ADA4EA8D78961DA4215F30ADA 20C1E383
60067 8 1 98CBA1327356A4C9C3FF676D4DC98BB11C067B31
EOF
}
# return 10 = dig failed
digTEST5() {
cat <<EOF
;; connection timed out; no servers could be reached
EOF
return 10
}
digPTEST6() {
cat <<EOF
ns1.dns.nl.
ns2.dns.nl.
ns5.dns.nl.
ns3.dns.nl.
sns-pb.isc.org.
EOF
}
#accountingfinance.nl;KSK;retire;2018-04-30 17:20:20;2048;8;370d04521504b61a10cfd9f1e489b92e;LocalHSM;55559
#accountingfinance.nl;KSK;ready;waiting for ds-seen;2048;8;c0cea25af6898fc0e6d4ed96e7042ae2;LocalHSM;26047
testSupportedVersion() {
version=$(ods_version)
assertNotNull $version
majorversion=${version%%.*}
assertTrue "[ $majorversion -ge 1 ]"
assertTrue "[ $majorversion -le 2 ]"
}
testTrim() {
assertSame "aaa bbbb cccc" "$( echo ' aaa bbbb cccc ' | trim)"
}
# Zoek een domein met 1 keytag op in DNS
testGet1KeytagFromDNS() {
# setup
digbak=$DIG
DIG=digTEST
dns=$(mktemp)
zone="uvt.nl"
get_keytags_from_dns $zone $dns
tags=$(cat $dns)
assertSame "21035" "$tags"
# cleanup
rm "$dns"
DIG=$digbak
}
# Zoek een domein met meerdere keytag op in DNS
testGetKeytagsFromDNS() {
# setup
digbak=$DIG
DIG=digTEST2
# dns=$(mktemp)
zone="tilburguniversity.edu"
get_keytags_from_dns $zone $dns
tags=$(cat $dns)
assertSame "30701
33827
49351" "$tags"
# cleanup
rm $dns
DIG=$digbak
}
# Basisfunctionaliteit van get_keytags_from_ods testen
testGetKeytagsFromODS() {
enforcerBAK=$ENFORCER
ENFORCER=enforcerTEST
zone="tilt.nl"
get_keytags_from_ods $zone $ods $w4s $w4g
assertSame "48134
49087
60559" "$(cat $ods)"
assertSame "49087" "$(cat $w4s)"
assertSame "48134" "$(cat $w4g)"
ENFORCER=$enforcerBAK
}
# In DNS: '35389 21892'
# In ODS: '21892 35389'
# Waiting for ds-seen: '21892'
# Waiting for ds-gone: '35389'
# Basisfunctionaliteit van compareketags testen
testCompareKeytags() {
enforcerBAK=$ENFORCER
digBAK=$DIG
digpBAK=$DIGP
keylistBAK=$keylist
keylist=$(mktemp)
ENFORCER=enforcerTEST3
DIG=digTEST3
DIGP=digPTEST6
zone="mijnuvt.nl"
get_keytags_from_dns $zone $dns
get_keytags_from_ods $zone $ods $w4s $w4g
compare_keytags $dns $ods $w4s $w4g $seen $notseen $gone $notgone $unknown
print_debug
assertSame "21892 35389 54321" "$(cat $dns | row)"
assertSame "21892 35389" "$(cat $ods | row)"
assertSame "21892" "$(cat $seen)"
assertSame "" "$(cat $notseen)"
assertSame "" "$(cat $gone)"
assertSame "35389" "$(cat $notgone)"
assertSame "54321" "$(cat $unknown)"
ENFORCER=$enforcerBAK
DIG=$digBAK
DIGP=$digpBAK
rm -f $keylist
keylist=$keylistBAK
}
# Iedere keytag niet meer dan 1 keer behandelen.
# Dubbele tags kunnen optreden wanneer verschillende DS'en
# van dezelfde key worden gepubliceerd (met verschillende hash-algorimtes, bv SHA256 en SHA512).
testGetDoubleKeytagsFromDNS() {
# setup
digbak=$DIG
DIG=digTEST4
zone="eurovalues.be"
get_keytags_from_dns $zone $dns
tags=$(cat $dns | row)
assertSame "27032 60067" "$tags"
# cleanup
DIG=$digbak
}
# Gaan we goed om met falende DNS-servers?
testFailedDIG() {
# setup
digpbak=$DIG
DIGP=digTEST5
DIG=digTEST5
dns=$(mktemp)
zone="tilburguniversity.edu"
log 4 "Expect the following error message between the lines:"
log 4 "tilburguniversity.edu: error: DNS-server=';; connection timed out; no servers could be reached': ;; connection timed out; no servers could be reached)"
log 4 "--- start line ---------------"
get_keytags_from_dns $zone $dns
log 4 "--- stop line ----------------"
tags=$(cat $dns)
assertSame "" "$tags"
# cleanup
rm $dns
DIGP=$digpbak
}
# Wordt bij een geforceerde (de)activate de juiste keys ge(de)activeert?
# In DNS: '33827 35389'
# In ODS: '21892 35389'
# Waiting for ds-seen: '21892'
# Waiting for ds-gone: '35389'
testForceActivate() {
# setup
echo -e '33827\n35389' > $seen
echo '' > $gone
echo '21892' > $w4s
echo '35389' > $w4g
zone="mijnuvt.nl"
force_activate $zone $w4s $w4g $seen $gone > /dev/null
# cleanup
assertSame "$(cat $seen)" '21892'
assertSame "$(cat $gone)" '35389'
}
# Hide differences between ODS versions
# keytagcol = The location of the column with the keytag in the output of ksm-util
# seperator = column seperator
# ods_verbose = What options to use to get verbose output
case $(ods_version) in
1.3*) ENFORCER=/usr/bin/ods-ksmutil; keytagcol=9 ; transcol=4; seperator=' '; ods_verbose='-v' ;;
1.4*) ENFORCER=/usr/bin/ods-ksmutil; keytagcol=12; transcol=4; seperator=' '; ods_verbose='-v' ;;
2*) ENFORCER=/usr/sbin/ods-enforcer; keytagcol=9 ; transcol=4; seperator=';'; ods_verbose='-v -p' ;;
*) echo "Unknown OpenDNSSEC version, bailing out!"; exit 1 ;;
esac
# default options
activate="no" # do not activate by default
force="no" # only activate keys that are really available
LOGLEVEL="3" # only print important messages
zones=""
# parse cli options
until [ -z "$*" ];
do
option="$1"
shift
case $option in
-h|--help) usage ;;
--activate) activate="yes" ;;
--force) activate="yes" ; force="yes";;
--quiet) LOGLEVEL=2 ;;
--verbose) LOGLEVEL=4 ;;
-d|--debug) LOGLEVEL=9 ;;
--all) zones=$(echo ' '; $ENFORCER key list 2>/dev/null | nosql | egrep -v 'Keys:|Zone:' | awk '/waiting for ds-/ {print $1}' | sort -u);; # start with a space so $zones is not empty
--really-all) zones=$(echo ' '; $ENFORCER key list 2>/dev/null | nosql | egrep -v 'Keys:|Zone:' | awk '{print $1}' | sort -u);;
--test) USE_SHUNIT=true ;;
--*) usage ;;
*) zones="$zones $option" ;;
esac
done
if [ -z "$zones" ] && ! $USE_SHUNIT; then
usage
fi
# create temporary files
inittemp() {
cleantemp
dns=$(mktemp) # keys found in DNS
ods=$(mktemp) # keys known to OpenDNSSEC
w4s=$(mktemp) # waiting for ds-sseen
w4g=$(mktemp) # waiting for ds-gone
seen=$(mktemp) # newly seen in DNS
notseen=$(mktemp) # not yet in DNS
gone=$(mktemp) # gone from DNS
notgone=$(mktemp) # still in DNS
unknown=$(mktemp) # keys found in DNS that are unknown to ODS
}
cleantemp() {
rm -f $dns $ods $w4s $w4g $seen $notseen $gone $notgone $unknown
}
# validate the input
# - check return value of dig
# - check for zones without any keys
valid_input() {
dig_ret="$1"
dns="$2"
if [ $ret != 0 ] ; then
log 2 "DNS failed for $zone with code $ret. Skipping zone."
return 1
fi
if [ ! -s "$dns" ]; then # $dns should never be empty
log 2 "$zone: warning: no key(s) found in DNS at all for zone $zone."
if [ "$force" == "no" ]; then # force activation of zones without (public) dnssec
log 2 "Skipping zone without DNSKEYs. Use --force to override."
return 1
else
log 2 "Proceeding without DNSKEYs because of --force."
return 0
fi
fi
return 0
}
print_results() {
zone="$1"
notseen="$2"
notgone="$3"
unknown="$4"
# logging
if [ -s "$notseen" ]; then
log 3 "$zone: The key(s) with tag(s) $(cat $notseen | row) are not yet present in DNS."
else
if [ ! -s "$w4s" ]; then
log 4 "$zone: No unactivated keys known by ODS, nothing to do."
else
log 4 "$zone: All new keys have been activated."
fi
fi
if [ -s "$notgone" ]; then
log 3 "$zone: The key(s) with tag(s) $(cat $notgone | row) are still present in DNS."
else
if [ ! -s "$w4g" ]; then
log 4 "$zone: No retired or dead keys known by ODS, nothing to do."
else
log 4 "$zone: All (known) retired and/or dead keys have been removed from DNS."
fi
fi
if [ -s "$unknown" ]; then
log 3 "$zone: Unknown key(s) with tag(s) '$(cat $unknown | row)' found in DNS."
fi
}
inittemp # create temporary files
keylist=$(mktemp) # raw keylist from ODS (cached for performance reasons)
# keylist should be cached and is therefor not created/cleaned with inittemp
# unit testing
if $USE_SHUNIT; then
inittemp
source /usr/bin/shunit2
cleantemp
exit 0
fi
for zone in $zones; do
inittemp
get_keytags_from_ods $zone $ods $w4s $w4g
get_keytags_from_dns $zone $dns
ret=$?
valid_input $ret $dns || continue
compare_keytags $dns $ods $w4s $w4g $seen $notseen $gone $notgone $unknown
print_debug
# activation
if [ "$activate" == "yes" ]; then
if [ "$force" == "yes" ]; then # force activation of zones without (public) dnssec
force_activate $zone $w4s $w4g $seen $gone
fi
notify_ods $zone $seen $gone # this is were all the action is
fi
# logging
print_results $zone $notseen $notgone $unknown
done
cleantemp