Server IP : 195.201.23.43 / Your IP : 3.17.135.12 Web Server : Apache System : Linux webserver2.vercom.be 5.4.0-192-generic #212-Ubuntu SMP Fri Jul 5 09:47:39 UTC 2024 x86_64 User : kdecoratie ( 1041) PHP Version : 7.1.33-63+ubuntu20.04.1+deb.sury.org+1 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals, MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /usr/share/webmin/virtual-server/ |
Upload File : |
#!/usr/bin/perl =head1 modify-dns.pl Change DNS settings for virtual servers This program updates DNS-related options for one or more servers, selected using the C<--domain> or C<--all-domains> flags. Or you can select all domains that don't have their own private IP address with C<--all-nonvirt-domains>. To enable SPF for a domain, using C<--spf> option, and to turn it off use C<--no-spf>. By default, the SPF record will be created using the settings from the DNS section of the domain's server template. To add allowed hostname, MX domains or IP addresses, use the C<--spf-add-a>, C<--spf-add-mx>, C<--spf-add-ip4> and C<--spf-add-ip6> options respectively. Each of which must be followed by a single host, domain or IP address. Or you can use C<--spf-add-include> followed by a domain name who's SPF policy will be included in this one. Similarly, the C<--spf-remove-a>, C<--spf-remove-mx>, C<--spf-remove-ip4>, C<--spf-remove-ip6> and C<--spf-remove-include> options will remove the following host, domain or IP address from the allowed list for the specified domains. To control how SPF treats senders not in the allowed hosts list, use one of the C<--spf-all-disallow>, C<--spf-all-discourage>, C<--spf-all-neutral>, C<--spf-all-allow> or C<--spf-all-default> parameters. To enable the DMARC DNS record for a domain, use the C<--dmarc> flag - or to disable it, use C<--no-dmarc>. The DMARC action for other mail servers to perform can be set with the C<--dmarc-policy> flag, and the percentage of messages it should be applied to can be set with C<--dmarc-percent>. This command can also be used to add and remove DNS records from all the selected domains. Adding is done with the C<--add-record> flag, which must be followed by a single parameter containing the record name, type and value. Alternately, you can use C<--add-record-with-ttl> followed by the name, type, TTL and value. If your cloud DNS provider supports proxy records, you can use the C<--add-proxy-record> with the same parameters as C<--add-record>. Conversely, deletion is done with the C<--remove-record> flag, followed by a single parameter containing the name and type of the record(s) to delete. You can also optionally include the record values, to disambiguate records with the same name but different values (like MX records). Both the additional and deletion flags can be given multiple times. Similarly, the default TTL for records can be set with the C<--ttl> flag followed by a number in seconds. Suffixes like h, m and d are also allowed to specific a TTL in hours, minutes or days. Alternately, the C<--all-ttl> flag can be used to set the TTL for all records in the domain. You can also add or remove slave DNS servers for this domain, assuming that they have already been setup in Webmin's BIND DNS Server module. To add a specific slave host, use the C<--add-slave> flag followed by a hostname. Or to add them all, use the C<--add-all-slaves> flag. To remove a single slave host, use the C<--remove-slave> command followed by a hostname. Or to remove any slave hosts that are no longer valid (ie. because they were removed from Webmin), use the C<--sync-all-slaves> flag. If your system is on an internal network and made available to the Internet via a router doing NAT, the IP address of a domain in DNS may be different from it's IP on the actual system. To set this, the C<--dns-ip> flag can be given, followed by the external IP address to use. To revert to using the real IP in DNS, use C<--no-dns-ip> instead. In both cases, the actual DNS records managed by Virtualmin will be updated. To add TLSA records (for publishing SSL certs) to selected domains, use the C<--enable-tlsa> flag. Similarly the C<--disable-tlsa> removes them, and the C<--sync-tlsa> updates them in domains where they already exist. If a virtual server is a sub-domain of another server, you can move it's DNS records out into a separate zone file with the C<--disable-subdomain> flag. Or if eligible, you can combine the zones with C<--enable-subdomain>. If this domain has a parent domain also hosted on the same system but not sharding the same zone file, you can use the C<--add-parent-ds> flags to add required DNSSEC DS records to the parent. Alternately you can use C<--remove-parent-ds> to delete them, but this is not recommended as it may break DNSSEC validation. If you have Cloud DNS providers setup, you can move the domain to one with the C<--cloud-dns> flag followed by a provider name like C<cloudflare> or C<route53>. Alternately the domain can be moved back to local hosting with the flag C<--cloud-dns local>. Similarly, the C<--remote-dns> flag followed by a hostname can be used to move this domain to a remote Webmin DNS server, if one is configured. Or to move it back to local hosting, use the C<--local-dns> flag. =cut package virtual_server; if (!$module_name) { $main::no_acl_check++; $ENV{'WEBMIN_CONFIG'} ||= "/etc/webmin"; $ENV{'WEBMIN_VAR'} ||= "/var/webmin"; if ($0 =~ /^(.*)\/[^\/]+$/) { chdir($pwd = $1); } else { chop($pwd = `pwd`); } $0 = "$pwd/modify-dns.pl"; require './virtual-server-lib.pl'; $< == 0 || die "modify-dns.pl must be run as root"; } &require_bind(); @OLDARGV = @ARGV; $config{'dns'} || &usage("The BIND DNS server is not enabled for Virtualmin"); &set_all_text_print(); # Parse command-line args while(@ARGV > 0) { local $a = shift(@ARGV); if ($a eq "--domain") { push(@dnames, shift(@ARGV)); } elsif ($a eq "--all-domains") { $all_doms = 1; } elsif ($a eq "--all-nonvirt-domains") { $all_doms = 2; } elsif ($a eq "--spf") { $spf = 1; } elsif ($a eq "--no-spf") { $spf = 0; } elsif ($a =~ /^--spf-add-(a|mx|ip4|ip6|include)$/) { $add = shift(@ARGV); $type = $1; $add =~ /^[a-z0-9\.\-\_:]+$/ || &usage("$a must be followed by a hostname or IP address"); push(@{$add{$type}}, $add); } elsif ($a =~ /^--spf-remove-(a|mx|ip4|ip6|include)$/) { $rem = shift(@ARGV); $type = $1; $rem =~ /^[a-z0-9\.\-\_:]+$/ || &usage("$a must be followed by a hostname or IP address"); push(@{$rem{$type}}, $rem); } elsif ($a =~ /^--spf-all-(disallow|discourage|neutral|allow|default)$/){ $spfall = $1 eq "disallow" ? 3 : $1 eq "discourage" ? 2 : $1 eq "neutral" ? 1 : $1 eq "allow" ? 0 : -1; } elsif ($a eq "--dmarc") { $dmarc = 1; } elsif ($a eq "--no-dmarc") { $dmarc = 0; } elsif ($a eq "--dmarc-policy") { $dmarcp = shift(@ARGV); $dmarcp =~ /^(none|reject|quarantine)$/ || &usage("--dmarc-policy must be followed by none, ". "reject or quarantine"); } elsif ($a eq "--dmarc-percent") { $dmarcpct = shift(@ARGV); $dmarcpct =~ /^\d+$/ && $dmarcpct >= 0 && $dmarcpct <= 100 || &usage("--dmarc-percent must be followed by an ". "integer between 0 and 100"); } elsif ($a eq "--dns-ip") { $dns_ip = shift(@ARGV); &check_ipaddress($dns_ip) || &usage("--dns-ip must be followed by an IP address"); } elsif ($a eq "--no-dns-ip") { $dns_ip = ""; } elsif ($a eq "--add-record") { my ($name, $type, @values) = split(/\s+/, shift(@ARGV)); $name && $type && @values || &usage("--add-record must be followed by the record name, type and values, all in one parameter"); push(@addrecs, [ $name, $type, undef, \@values, 0 ]); } elsif ($a eq "--add-record-with-ttl") { my ($name, $type, $ttl, @values) = split(/\s+/, shift(@ARGV)); $name && $type && $ttl && @values || &usage("--add-record-with-ttl must be followed by the record name, type, TTL and values, all in one parameter"); push(@addrecs, [ $name, $type, $ttl, \@values, 0 ]); } elsif ($a eq "--add-proxied-record") { my ($name, $type, @values) = split(/\s+/, shift(@ARGV)); $name && $type && @values || &usage("--add-proxied-record must be followed by the record name, type and values, all in one parameter"); push(@addrecs, [ $name, $type, undef, \@values, 1 ]); } elsif ($a eq "--remove-record") { my ($name, $type, @values) = split(/\s+/, shift(@ARGV)); $name && $type || &usage("--remove-record must be followed by the record name and type, all in one parameter"); push(@delrecs, [ $name, $type, @values ]); } elsif ($a eq "--ttl") { $ttl = shift(@ARGV); $ttl =~ /^\d+(s|m|h|d)?$/ || &usage("--ttl must be followed by a number with a valid suffix"); } elsif ($a eq "--all-ttl") { $allttl = shift(@ARGV); $allttl =~ /^\d+(s|m|h|d)?$/ || &usage("--all-ttl must be followed by a number with a valid suffix"); $ttl = $allttl; } elsif ($a eq "--increment-soa") { $bumpsoa = 1; } elsif ($a eq "--add-slave") { push(@addslaves, shift(@ARGV)); } elsif ($a eq "--remove-slave") { push(@delslaves, shift(@ARGV)); } elsif ($a eq "--add-all-slaves") { $addallslaves = 1; } elsif ($a eq "--sync-all-slaves") { $syncallslaves = 1; } elsif ($a eq "--enable-dnssec") { $dnssec = 1; } elsif ($a eq "--disable-dnssec") { $dnssec = 0; } elsif ($a eq "--enable-tlsa") { $tlsa = 1; } elsif ($a eq "--disable-tlsa") { $tlsa = 0; } elsif ($a eq "--sync-tlsa") { $tlsa = 2; } elsif ($a eq "--enable-subdomain") { $submode = 1; } elsif ($a eq "--disable-subdomain") { $submode = 0; } elsif ($a eq "--multiline") { $multiline = 1; } elsif ($a eq "--cloud-dns") { $clouddns = shift(@ARGV); } elsif ($a eq "--cloud-dns-import") { $clouddns_import = 1; } elsif ($a eq "--remote-dns") { $remotedns = shift(@ARGV); } elsif ($a eq "--local-dns") { $remotedns = ""; } elsif ($a eq "--add-parent-ds") { $parentds = 1; } elsif ($a eq "--remove-parent-ds") { $parentds = 0; } elsif ($a eq "--help") { &usage(); } else { &usage("Unknown parameter $a"); } } @dnames || $all_doms || usage("No domains specified"); defined($spf) || %add || %rem || defined($spfall) || defined($dns_ip) || @addrecs || @delrecs || @addslaves || @delslaves || $addallslaves || $ttl || defined($dmarc) || $dmarcp || defined($dmarcpct) || defined($dnssec) || defined($tlsa) || $syncallslaves || defined($submode) || $clouddns || defined($remotedns) || defined($parentds) || defined($clouddns_import) || &usage("Nothing to do"); # Get domains to update if ($all_doms == 1) { @doms = grep { $_->{'dns'} } &list_domains(); } elsif ($all_doms == 2) { @doms = grep { $_->{'dns'} && !$_->{'virt'} } &list_domains(); } else { foreach $n (@dnames) { $d = &get_domain_by("dom", $n); $d || &usage("Domain $n does not exist"); $d->{'dns'} || &usage("Virtual server $n does not have a DNS domain"); push(@doms, $d); } } # Validate slave args &require_bind(); if (@addslaves && $addallslaves) { &usage("Both --add-slave and --add-all-slaves cannot be specified at the same time"); } @slaveservers = &bind8::list_slave_servers(); if ($addallslaves) { @addslaves = map { $_->{'host'} } @slaveservers; @addslaves || &usage("No slave DNS servers have been setup in Webmin's BIND module"); } elsif (@addslaves) { foreach $s (@addslaves) { ($ss) = grep { $_->{'host'} eq $s } @slaveservers; $ss || &usage("No slave DNS server with hostname $s exists"); } } if (@delslaves) { foreach $s (@delslaves) { ($ss) = grep { $_->{'host'} eq $s } @slaveservers; $ss || &usage("No slave DNS server with hostname $s exists"); } } # Check for remote/cloud conflict if ($clouddns && defined($remotedns)) { &usage("Remote and Cloud DNS providers cannot be set at the same time"); } # Validate the Cloud DNS provider if ($clouddns) { if ($clouddns eq "services") { $config{'provision_dns'} || &usage("Cloudmin Services for DNS is not enabled"); } elsif ($clouddns ne "local") { my @cnames = map { $_->{'name'} } &list_dns_clouds(); &indexof($clouddns, @cnames) >= 0 || &usage("Valid Cloud DNS providers are : ". join(" ", @cnames)); } } # Validate remote DNS option if (defined($remotedns)) { defined(&list_remote_dns) || &usage("Remote DNS servers are not supported"); my @remote = &list_remote_dns(); if ($remotedns eq "") { ($rserver) = grep { $_->{'id'} == 0 } @remote; $rserver ||&usage("This system cannot be used as a DNS server"); } else { ($rserver) = grep { $_->{'host'} eq $remotedns } @remote; $rserver || &usage("Remote DNS server $remotedns not found"); } $rserver->{'slave'} && &usage("Remote DNS server $rserver->{'host'} ". "cannot be used for master zones"); } # Do it for all domains foreach $d (@doms) { &$first_print("Updating server $d->{'dom'} .."); &obtain_lock_dns($d); &$indent_print(); $oldd = { %$d }; $cloud = &get_domain_dns_cloud($d); $currspf = &get_domain_spf($d); if (defined($spf)) { # Turn SPF on or off if ($spf == 1 && !$currspf) { # Need to enable, with default settings &$first_print($text{'spf_enable'}); &save_domain_spf($d, $currspf=&default_domain_spf($d)); &$second_print($text{'setup_done'}); } elsif ($spf == 0 && $currspf) { # Need to disable &$first_print($text{'spf_disable'}); &save_domain_spf($d, undef); &$second_print($text{'setup_done'}); $currspf = undef; } } $currdmarc = &get_domain_dmarc($d); if (defined($dmarc)) { # Turn DMARC on or off if ($dmarc == 1 && !$currdmarc) { # Need to enable, with default settings &$first_print($text{'spf_dmarcenable'}); $err = &save_domain_dmarc($d, $currdmarc = &default_domain_dmarc($d)); &$second_print($err || $text{'setup_done'}); } elsif ($dmarc == 0 && $currdmarc) { # Need to disable &$first_print($text{'spf_dmarcdisable'}); $err = &save_domain_dmarc($d, undef); &$second_print($err || $text{'setup_done'}); $currdmarc = undef; } } if ((%add || %rem || defined($spfall)) && $currspf) { # Update a, mx ip4 and ip6 in SPF record &$first_print($text{'spf_change'}); foreach $t (keys %add) { foreach $a (@{$add{$t}}) { push(@{$currspf->{$t.":"}}, $a); } $currspf->{$t.":"} = [ &unique(@{$currspf->{$t.":"}}) ]; } foreach $t (keys %rem) { foreach $a (@{$rem{$t}}) { $currspf->{$t.":"} = [ grep { $_ ne $a } @{$currspf->{$t.":"}} ]; } } if (defined($spfall)) { if ($spfall < 0) { delete($currspf->{'all'}); } else { $currspf->{'all'} = $spfall; } } &save_domain_spf($d, $currspf); &$second_print($text{'setup_done'}); } if (($dmarcp || defined($dmarcpct)) && $currdmarc) { # Update current DMARC record &$first_print($text{'spf_dmarcchange'}); if ($dmarcp) { $currdmarc->{'p'} = $dmarcp; } if (defined($dmarcpct)) { $currdmarc->{'pct'} = $dmarcpct; } &save_domain_dmarc($d, $currdmarc); &$second_print($text{'setup_done'}); } if (defined($dns_ip)) { if ($dns_ip) { # Changing IP address for DNS $d->{'dns_ip'} = $dns_ip; } else { # Resetting DNS IP address to default delete($d->{'dns_ip'}); } &modify_dns($d, $oldd); &save_domain($d); } # Remove records from the domain local ($recs, $file); local $changed; if (@delrecs) { &$first_print(&text('spf_delrecs', scalar(@delrecs))); if (!$recs) { &pre_records_change($d); ($recs, $file) = &get_domain_dns_records_and_file($d); } local @alld; foreach my $rn (@delrecs) { my ($name, $type, @values) = @$rn; if ($name !~ /\.$/) { $name .= ".".$d->{'dom'}."."; } local @d = grep { $_->{'name'} eq $name && lc($_->{'type'}) eq lc($type) } @$recs; if (@values) { # Also filter by values @d = grep { join(" ", @values) eq join(" ", @{$_->{'values'}}) } @d; } push(@alld, @d); } foreach my $r (@alld) { &delete_dns_record($recs, $file, $r); $changed++; } &$second_print($text{'setup_done'}); } # Add records to the domain if (@addrecs) { &$first_print(&text('spf_addrecs', scalar(@addrecs))); if (!$recs) { &pre_records_change($d); ($recs, $file) = &get_domain_dns_records_and_file($d); } foreach my $rn (@addrecs) { my ($name, $type, $ttl, $values, $proxied) = @$rn; if ($name !~ /\.$/ && $name ne "\@") { $name .= ".".$d->{'dom'}."."; } my $r = { 'name' => $name, 'type' => $type, 'ttl' => $ttl, 'values' => $values, 'proxied' => $proxied }; my ($clash) = grep { $_->{'name'} eq $name && &bind8::join_record_values($_) eq &bind8::join_record_values($r) } @$recs; if ($clash) { &$second_print(&text('spf_eaddrecs', $r->{'name'})); } elsif ($proxied && (!$cloud || !$cloud->{'proxy'})) { &$second_print(&text('spf_eaddproxy', $r->{'name'})); } else { &create_dns_record($recs, $file, $r); $changed++; } } &$second_print($text{'setup_done'}); } # Set or modify default TTL if ($ttl && &supports_dns_defttl($d)) { &$first_print(&text('spf_ttl', $ttl)); if (!$recs) { &pre_records_change($d); ($recs, $file) = &get_domain_dns_records_and_file($d); } ($oldttl) = grep { $_->{'defttl'} } @$recs; if ($oldttl) { $oldttl->{'defttl'} = $ttl; &modify_dns_record($recs, $file, $oldttl); } else { &create_dns_record($recs, $file, $ttl); } $changed++; &$second_print($text{'setup_done'}); } elsif ($ttl && !&supports_dns_defttl($d)) { &$first_print(&text('spf_ttl', $ttl)); &$second_print($text{'spf_ettlsupport'}); } # Change the TTL on any records that have one if ($allttl) { if (!$recs) { &pre_records_change($d); ($recs, $file) = &get_domain_dns_records_and_file($d); } foreach my $r (@$recs) { if ($r->{'ttl'} && $r->{'type'} ne 'SOA') { $r->{'ttl'} = $ttl; &modify_dns_record($recs, $file, $r); $changed++; } } } # Enable or disable DNSSEC if (defined($dnssec)) { if (&can_domain_dnssec($d)) { # DNSSEC is supported for this domain &pre_records_change($d); $key = &has_domain_dnssec($d, $recs); if ($dnssec && !$key) { # Enable it &$first_print($text{'spf_enablednssec'}); $err = &enable_domain_dnssec($d); &$second_print($err || $text{'setup_done'}); $changed++; } elsif (!$dnssec && $key) { # Disable it &$first_print($text{'spf_disablednssec'}); $err = &disable_domain_dnssec($d); &$second_print($err || $text{'setup_done'}); $changed++; } # Records may have changed, so re-read ($recs, $file) = &get_domain_dns_records_and_file($d); } else { # Not supported on remote providers &$first_print($dnssec ? $text{'spf_enablednssec'} : $text{'spf_disablednssec'}); &$second_print($text{'spf_ednssecsupport'}); } } # Create or remove TLSA records if (defined($tlsa)) { &pre_records_change($d); if ($tlsa == 1) { &$first_print($text{'spf_enabletlsa'}); $err = &check_tlsa_support(); if ($err) { &$second_print(&text('spf_etlsa', $err)); } else { &sync_domain_tlsa_records($d, 1); &$second_print($text{'setup_done'}); $changed++; } } elsif ($tlsa == 0) { &$first_print($text{'spf_disabletlsa'}); &sync_domain_tlsa_records($d, 2); &$second_print($text{'setup_done'}); $changed++; } elsif ($tlsa == 2) { &$first_print($text{'spf_synctlsa'}); my @recs = &get_domain_tlsa_records($d); if (@recs) { &sync_domain_tlsa_records($d, 1); &$second_print($text{'setup_done'}); } else { &$first_print($text{'spf_esynctlsa'}); } } if ($changed) { # Records have changed, so re-read ($recs, $file) = &get_domain_dns_records_and_file($d); } } # Move into a DNS sub-domain if (defined($submode)) { if ($submode == 1) { # Turning on sub-domain mode &$first_print($text{'spf_enablesub'}); if ($d->{'dns_submode'}) { &$second_print($text{'spf_enablesubalready'}); } elsif ($err = &save_dns_submode($d, 1)) { &$second_print(&text('spf_eenablesub', $err)); } else { &$second_print($text{'setup_done'}); } } else { # Turning off sub-domain mode &$first_print($text{'spf_disablesub'}); if (!$d->{'dns_submode'}) { &$second_print($text{'spf_enablesubalready'}); } elsif ($err = &save_dns_submode($d, 0)) { &$second_print(&text('spf_eenablesub', $err)); } else { &$second_print($text{'setup_done'}); } } } # Add or remove DS records in parent if (defined($parentds)) { my $err; if ($parentds) { &$first_print($text{'spf_enableds'}); $err = &add_parent_dnssec_ds_records($d); } else { &$first_print($text{'spf_disableds'}); $err = &delete_parent_dnssec_ds_records($d); } if ($err) { &$second_print(&text('spf_eenablesub', $err)); } else { &$second_print($text{'setup_done'}); } } if ($changed || $bumpsoa) { my $err = &post_records_change($d, $recs, $file); if ($err) { &$second_print(&text('spf_epostchange', $err)); } &reload_bind_records($d); } # Add to slave DNS servers if (@addslaves) { &create_zone_on_slaves($d, join(" ", @addslaves)); } if (@delslaves) { &delete_zone_on_slaves($d, join(" ", @delslaves)); } # Remove slaves that are no longer valid if ($syncallslaves) { my @ds = split(/\s+/, $d->{'dns_slave'}); my %slavenames = map { $_->{'host'}, $_ } @slaveservers; @ds = grep { $slavename{$_} } @ds; $d->{'dns_slave'} = join(" ", @ds); } # Change DNS Cloud if (defined($clouddns_import)) { $d->{'dns_cloud_import'} = $clouddns_import; } if ($clouddns) { if ($clouddns eq "local") { &$first_print($text{'spf_dnslocal'}); } else { my ($c) = grep { $_->{'name'} eq $clouddns } &list_dns_clouds(); &$first_print(&text('spf_dnscloud', $c->{'name'})); } &$indent_print(); my $err = &modify_dns_cloud($d, $clouddns); &$outdent_print(); if ($err) { &$second_print(&text('spf_eclouddns', $err)); } else { &$second_print($text{'setup_done'}); } } # Change remote DNS server if ($rserver) { if ($rserver->{'id'} == 0) { &$first_print($text{'spf_dnsrlocal'}); } else { &$first_print(&text('spf_dnsrhost',$rserver->{'host'})); } &$indent_print(); my $err = &modify_dns_cloud($d, "local", $rserver); &$outdent_print(); if ($err) { &$second_print(&text('spf_eclouddns', $err)); } else { &$second_print($text{'setup_done'}); } } &$outdent_print(); &save_domain($d); &release_lock_dns($d); &$second_print(".. done"); } &run_post_actions(); &virtualmin_api_log(\@OLDARGV); sub usage { print "$_[0]\n\n" if ($_[0]); print "Changes DNS settings for one or more domains.\n"; print "\n"; print "virtualmin modify-dns --domain name | --all-domains | --all-nonvirt-domains\n"; print " [--spf | --no-spf]\n"; print " [--spf-add-a hostname]*\n"; print " [--spf-add-mx domain]*\n"; print " [--spf-add-ip4 address]*\n"; print " [--spf-add-ip6 address]*\n"; print " [--spf-remove-a hostname]*\n"; print " [--spf-remove-mx domain]*\n"; print " [--spf-remove-ip4 address]*\n"; print " [--spf-remove-ip6 address]*\n"; print " [--spf-all-disallow | --spf-all-discourage |\n"; print " --spf-all-neutral | --spf-all-allow |\n"; print " --spf-all-default]\n"; print " [--dmarc | --no-dmarc]\n"; print " [--dmarc-policy none|quarantine|reject]\n"; print " [--dmarc-percent number]\n"; print " [--add-record \"name type value\"]\n"; print " [--add-record-with-ttl \"name type TTL value\"]\n"; print " [--add-proxy-record \"name type value\"]\n"; print " [--remove-record \"name type value\"]\n"; print " [--ttl seconds | --all-ttl seconds]\n"; print " [--add-slave hostname]* | [--add-all-slaves]\n"; print " [--remove-slave hostname]* | [--sync-all-slaves]\n"; print " [--dns-ip address | --no-dns-ip]\n"; print " [--enable-dnssec | --disable-dnssec]\n"; print " [--enable-tlsa | --disable-tlsa | --sync-tlsa]\n"; print " [--enable-subdomain | --disable-subdomain]\n"; print " [--cloud-dns provider|\"local\"]\n"; print " [--cloud-dns-import]\n"; print " [--remote-dns hostname | --local-dns]\n"; print " [--add-parent-ds | --remove-parent-ds]\n"; exit(1); }Private