diff --git a/CHANGES b/CHANGES
index e50573af38..9863b78bfe 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+3559. [func] Check that both forms of Sender Policy Framework
+ records exist or do not exist. [RT #33355]
+
3558. [bug] IXFR of a DLZ stored zone was broken. [RT #33331]
3557. [bug] Reloading redirect zones was broken. [RT #33292]
diff --git a/bin/check/named-checkconf.c b/bin/check/named-checkconf.c
index 53e6091fb9..6e832dd6c3 100644
--- a/bin/check/named-checkconf.c
+++ b/bin/check/named-checkconf.c
@@ -294,6 +294,18 @@ configure_zone(const char *vclass, const char *view,
zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
}
+ obj = NULL;
+ if (get_maps(maps, "check-spf", &obj)) {
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ zone_options |= DNS_ZONEOPT_CHECKSPF;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ zone_options &= ~DNS_ZONEOPT_CHECKSPF;
+ } else
+ INSIST(0);
+ } else {
+ zone_options |= DNS_ZONEOPT_CHECKSPF;
+ }
+
obj = NULL;
if (get_checknames(maps, &obj)) {
if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
diff --git a/bin/check/named-checkzone.c b/bin/check/named-checkzone.c
index 8d978569e3..a13cfa7d5c 100644
--- a/bin/check/named-checkzone.c
+++ b/bin/check/named-checkzone.c
@@ -155,19 +155,21 @@ main(int argc, char **argv) {
if (progmode == progmode_compile) {
zone_options |= (DNS_ZONEOPT_CHECKNS |
DNS_ZONEOPT_FATALNS |
+ DNS_ZONEOPT_CHECKSPF |
DNS_ZONEOPT_CHECKDUPRR |
DNS_ZONEOPT_CHECKNAMES |
DNS_ZONEOPT_CHECKNAMESFAIL |
DNS_ZONEOPT_CHECKWILDCARD);
} else
- zone_options |= DNS_ZONEOPT_CHECKDUPRR;
+ zone_options |= (DNS_ZONEOPT_CHECKDUPRR |
+ DNS_ZONEOPT_CHECKSPF);
#define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0)
isc_commandline_errprint = ISC_FALSE;
while ((c = isc_commandline_parse(argc, argv,
- "c:df:hi:jJ:k:L:m:n:qr:s:t:o:vw:DF:M:S:W:"))
+ "c:df:hi:jJ:k:L:m:n:qr:s:t:o:vw:DF:M:S:T:W:"))
!= EOF) {
switch (c) {
case 'c':
@@ -389,6 +391,18 @@ main(int argc, char **argv) {
}
break;
+ case 'T':
+ if (ARGCMP("warn")) {
+ zone_options |= DNS_ZONEOPT_CHECKSPF;
+ } else if (ARGCMP("ignore")) {
+ zone_options &= ~DNS_ZONEOPT_CHECKSPF;
+ } else {
+ fprintf(stderr, "invalid argument to -T: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+
case 'W':
if (ARGCMP("warn"))
zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
diff --git a/bin/check/named-checkzone.docbook b/bin/check/named-checkzone.docbook
index 934993dfce..98d3fc3ff9 100644
--- a/bin/check/named-checkzone.docbook
+++ b/bin/check/named-checkzone.docbook
@@ -80,6 +80,7 @@
+
@@ -105,6 +106,7 @@
+
@@ -419,6 +421,18 @@
+
+ -T mode
+
+
+ Check if Sender Policy Framework records (TXT and SPF)
+ both exist or both don't exist. A warning is issued
+ if they don't match. Possible modes are
+ "warn" (default), "ignore".
+
+
+
+
-w directory
diff --git a/bin/named/config.c b/bin/named/config.c
index 2de1db3786..93cbd460f6 100644
--- a/bin/named/config.c
+++ b/bin/named/config.c
@@ -151,6 +151,7 @@ options {\n\
check-names response ignore;\n\
check-dup-records warn;\n\
check-mx warn;\n\
+ check-spf warn;\n\
acache-enable no;\n\
acache-cleaning-interval 60;\n\
max-acache-size 16M;\n\
diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c
index cffe4c5c71..47565c7a97 100644
--- a/bin/named/zoneconf.c
+++ b/bin/named/zoneconf.c
@@ -1259,6 +1259,17 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSIBLING,
cfg_obj_asboolean(obj));
+ obj = NULL;
+ result = ns_config_get(maps, "check-spf", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ check = ISC_TRUE;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ check = ISC_FALSE;
+ } else
+ INSIST(0);
+ dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSPF, check);
+
obj = NULL;
result = ns_config_get(maps, "zero-no-soa-ttl", &obj);
INSIST(result == ISC_R_SUCCESS && obj != NULL);
diff --git a/bin/tests/system/checkzone/tests.sh b/bin/tests/system/checkzone/tests.sh
index 59643b12cf..a727b411c8 100644
--- a/bin/tests/system/checkzone/tests.sh
+++ b/bin/tests/system/checkzone/tests.sh
@@ -50,6 +50,21 @@ cmp -s test.changed.db test.out1.db || ret=1
mv -f test.orig.db.jnl test.journal
$CHECKZONE -D -J test.journal -o test.out2.db test test.orig.db > /dev/null 2>&1 || ret=1
cmp -s test.changed.db test.out2.db || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking with spf warnings ($n)"
+ret=0
+$CHECKZONE example zones/spf.db > test.out1.$n 2>&1 || ret=1
+$CHECKZONE -T ignore example zones/spf.db > test.out2.$n 2>&1 || ret=1
+grep "'x.example' found SPF/TXT" test.out1.$n > /dev/null || ret=1
+grep "'y.example' found SPF/SPF" test.out1.$n > /dev/null || ret=1
+grep "'example' found SPF/" test.out1.$n > /dev/null && ret=1
+grep "'x.example' found SPF/" test.out2.$n > /dev/null && ret=1
+grep "'y.example' found SPF/" test.out2.$n > /dev/null && ret=1
+grep "'example' found SPF/" test.out2.$n > /dev/null && ret=1
+n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
diff --git a/bin/tests/system/checkzone/zones/spf.db b/bin/tests/system/checkzone/zones/spf.db
new file mode 100644
index 0000000000..ffa850ad79
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/spf.db
@@ -0,0 +1,21 @@
+; Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+;
+; Permission to use, copy, modify, and/or distribute this software for any
+; purpose with or without fee is hereby granted, provided that the above
+; copyright notice and this permission notice appear in all copies.
+;
+; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+; PERFORMANCE OF THIS SOFTWARE.
+
+@ 0 IN SOA . . 0 0 0 0 0
+@ 0 IN NS .
+@ 0 IN TXT "v=spf1 -all"
+@ 0 IN SPF "v=spf1 -all"
+x 0 IN TXT "v=spf1"
+y 0 IN SPF "v=spf1"
+y 0 IN TXT "a non spf record"
diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in
index e505d74d7f..3093512d60 100644
--- a/bin/tests/system/conf.sh.in
+++ b/bin/tests/system/conf.sh.in
@@ -64,7 +64,7 @@ SUBDIRS="acl additional allow_query addzone autosign builtin
dsdigest dscp ecdsa formerr forward glue gost ixfr inline limits
logfileconfig lwresd masterfile masterformat metadata
notify nsupdate pending pkcs11 redirect resolver rndc rpz
- rrl rrsetorder rsabigexponent sortlist smartsign staticstub
+ rrl rrsetorder rsabigexponent smartsign sortlist spf staticstub
statistics stub tkey tsig tsiggss unknown upforwd verify
views wildcard xfer xferquota zonechecks"
diff --git a/bin/tests/system/spf/clean.sh b/bin/tests/system/spf/clean.sh
new file mode 100644
index 0000000000..9c95122b66
--- /dev/null
+++ b/bin/tests/system/spf/clean.sh
@@ -0,0 +1,2 @@
+rm -f ns1/named.run
+rm -f ns1/named.memstats
diff --git a/bin/tests/system/spf/ns1/named.conf b/bin/tests/system/spf/ns1/named.conf
new file mode 100644
index 0000000000..7d5dcfb041
--- /dev/null
+++ b/bin/tests/system/spf/ns1/named.conf
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ ixfr-from-differences yes;
+};
+
+zone "spf" {
+ type master;
+ file "spf.db";
+};
+
+zone "warn" {
+ type master;
+ file "spf.db";
+ check-spf warn;
+};
+
+zone "nowarn" {
+ type master;
+ file "spf.db";
+ check-spf ignore;
+};
diff --git a/bin/tests/system/spf/ns1/spf.db b/bin/tests/system/spf/ns1/spf.db
new file mode 100644
index 0000000000..ffa850ad79
--- /dev/null
+++ b/bin/tests/system/spf/ns1/spf.db
@@ -0,0 +1,21 @@
+; Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+;
+; Permission to use, copy, modify, and/or distribute this software for any
+; purpose with or without fee is hereby granted, provided that the above
+; copyright notice and this permission notice appear in all copies.
+;
+; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+; PERFORMANCE OF THIS SOFTWARE.
+
+@ 0 IN SOA . . 0 0 0 0 0
+@ 0 IN NS .
+@ 0 IN TXT "v=spf1 -all"
+@ 0 IN SPF "v=spf1 -all"
+x 0 IN TXT "v=spf1"
+y 0 IN SPF "v=spf1"
+y 0 IN TXT "a non spf record"
diff --git a/bin/tests/system/spf/tests.sh b/bin/tests/system/spf/tests.sh
new file mode 100644
index 0000000000..6acd2836a3
--- /dev/null
+++ b/bin/tests/system/spf/tests.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+#
+# Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+n=1
+status=0
+
+echo "I:checking that SPF warnings have been correctly generated ($n)"
+ret=0
+
+grep "zone spf/IN: loaded serial 0" ns1/named.run > /dev/null || ret=1
+grep "'x.spf' found SPF/TXT" ns1/named.run > /dev/null || ret=1
+grep "'y.spf' found SPF/SPF" ns1/named.run > /dev/null || ret=1
+grep "'spf' found SPF/" ns1/named.run > /dev/null && ret=1
+
+grep "zone warn/IN: loaded serial 0" ns1/named.run > /dev/null || ret=1
+grep "'x.warn' found SPF/TXT" ns1/named.run > /dev/null || ret=1
+grep "'y.warn' found SPF/SPF" ns1/named.run > /dev/null || ret=1
+grep "'warn' found SPF/" ns1/named.run > /dev/null && ret=1
+
+grep "zone nowarn/IN: loaded serial 0" ns1/named.run > /dev/null || ret=1
+grep "'x.nowarn' found SPF/" ns1/named.run > /dev/null && ret=1
+grep "'y.nowarn' found SPF/" ns1/named.run > /dev/null && ret=1
+grep "'nowarn' found SPF/" ns1/named.run > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:exit status: $status"
+exit $status
diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml
index c8fc5cfbc5..2df02e586d 100644
--- a/doc/arm/Bv9ARM-book.xml
+++ b/doc/arm/Bv9ARM-book.xml
@@ -5343,6 +5343,7 @@ badresp:1,adberr:0,findfail:0,valfail:0]
check-mx-cname ( warn | fail | ignore );
check-srv-cname ( warn | fail | ignore );
check-sibling yes_or_no;
+ check-spf ( warn | fail | ignore );
allow-new-zones { yes_or_no };
allow-notify { address_match_list };
allow-query { address_match_list };
@@ -7212,6 +7213,12 @@ options {
checks use named-checkzone).
The default is yes.
+
+ Check that the two forms of Sender Policy Framework
+ records (TXT and SPF) either both exist or both
+ don't exist. Warnings are emitted it they don't
+ and be suppressed with check-spf.
+
@@ -7247,6 +7254,19 @@ options {
+
+ check-spf
+
+
+ When performing integrity checks, check that the
+ two forms of Sender Policy Framwork records (TXT
+ and SPF) both exist or both don't exist and issue
+ a warning if not met. The default is
+ warn.
+
+
+
+
zero-no-soa-ttl
@@ -10982,6 +11002,7 @@ view "external" {
check-names (warn|fail|ignore) ;
check-mx (warn|fail|ignore) ;
check-wildcard yes_or_no;
+ check-spf ( warn | fail | ignore );
check-integrity yes_or_no ;
dialup dialup_option ;
file string ;
@@ -11631,6 +11652,16 @@ zone zone_name class
+
+ check-spf
+
+
+ See the description of
+ check-spf in .
+
+
+
+
check-wildcard
diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h
index cedd63e052..1d1c6b3cae 100644
--- a/lib/dns/include/dns/zone.h
+++ b/lib/dns/include/dns/zone.h
@@ -87,6 +87,7 @@ typedef enum {
#define DNS_ZONEOPT_DNSKEYKSKONLY 0x10000000U /*%< dnssec-dnskey-kskonly */
#define DNS_ZONEOPT_CHECKDUPRR 0x20000000U /*%< check-dup-records */
#define DNS_ZONEOPT_CHECKDUPRRFAIL 0x40000000U /*%< fatal check-dup-records failures */
+#define DNS_ZONEOPT_CHECKSPF 0x80000000U /*%< check SPF records */
#ifndef NOMINUM_PUBLIC
/*
diff --git a/lib/dns/zone.c b/lib/dns/zone.c
index 15f573a708..592355a2b8 100644
--- a/lib/dns/zone.c
+++ b/lib/dns/zone.c
@@ -2610,6 +2610,30 @@ zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
return (ok);
}
+static isc_boolean_t
+isspf(const dns_rdata_t *rdata) {
+ char buf[1024];
+ const unsigned char *data = rdata->data;
+ unsigned int rdl = rdata->length, i = 0, tl, len;
+
+ while (rdl > 0U) {
+ len = tl = *data;
+ ++data;
+ --rdl;
+ INSIST(tl <= rdl);
+ if (len > sizeof(buf) - i - 1)
+ len = sizeof(buf) - i - 1;
+ memcpy(buf + i, data, len);
+ i += len;
+ data += tl;
+ rdl -= tl;
+ }
+ buf[i] = 0;
+ if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' '))
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
static isc_boolean_t
integrity_checks(dns_zone_t *zone, dns_db_t *db) {
dns_dbiterator_t *dbiterator = NULL;
@@ -2624,7 +2648,7 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
dns_name_t *name;
dns_name_t *bottom;
isc_result_t result;
- isc_boolean_t ok = ISC_TRUE;
+ isc_boolean_t ok = ISC_TRUE, have_spf, have_txt;
dns_fixedname_init(&fixed);
name = dns_fixedname_name(&fixed);
@@ -2702,7 +2726,7 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
0, 0, &rdataset, NULL);
if (result != ISC_R_SUCCESS)
- goto next;
+ goto checkspf;
result = dns_rdataset_first(&rdataset);
while (result == ISC_R_SUCCESS) {
dns_rdataset_current(&rdataset, &rdata);
@@ -2715,6 +2739,50 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
}
dns_rdataset_disassociate(&rdataset);
+ checkspf:
+ /*
+ * Check if there is a type TXT spf record without a type SPF
+ * RRset being present.
+ */
+ if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF))
+ goto next;
+ if (zone->rdclass != dns_rdataclass_in)
+ goto next;
+ have_spf = have_txt = ISC_FALSE;
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
+ 0, 0, &rdataset, NULL);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdataset_disassociate(&rdataset);
+ have_spf = ISC_TRUE;
+ }
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
+ 0, 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto notxt;
+ result = dns_rdataset_first(&rdataset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(&rdataset, &rdata);
+ have_txt = isspf(&rdata);
+ dns_rdata_reset(&rdata);
+ if (have_txt)
+ break;
+ result = dns_rdataset_next(&rdataset);
+ }
+ dns_rdataset_disassociate(&rdataset);
+
+ notxt:
+ if (have_spf != have_txt) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ const char *found = have_txt ? "TXT" : "SPF";
+ const char *need = have_txt ? "SPF" : "TXT";
+
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found SPF/%s "
+ "record but no SPF/%s record found, add "
+ "matching type %s record", namebuf, found,
+ need, need);
+ }
+
next:
dns_db_detachnode(db, &node);
result = dns_dbiterator_next(dbiterator);
diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c
index c65727f341..b2c2946ca5 100644
--- a/lib/isccfg/namedconf.c
+++ b/lib/isccfg/namedconf.c
@@ -549,6 +549,12 @@ static cfg_type_t cfg_type_checkmode = {
&cfg_rep_string, &checkmode_enums
};
+static const char *warn_enums[] = { "warn", "ignore", NULL };
+static cfg_type_t cfg_type_warn = {
+ "warn", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
+ &cfg_rep_string, &warn_enums
+};
+
static cfg_tuplefielddef_t checknames_fields[] = {
{ "type", &cfg_type_checktype, 0 },
{ "mode", &cfg_type_checkmode, 0 },
@@ -1588,6 +1594,7 @@ zone_clauses[] = {
{ "check-mx", &cfg_type_checkmode, 0 },
{ "check-mx-cname", &cfg_type_checkmode, 0 },
{ "check-sibling", &cfg_type_boolean, 0 },
+ { "check-spf", &cfg_type_warn, 0 },
{ "check-srv-cname", &cfg_type_checkmode, 0 },
{ "check-wildcard", &cfg_type_boolean, 0 },
{ "dialup", &cfg_type_dialuptype, 0 },