Handle hostnames with upper-case letters
[webmin.git] / bind8 / create_master.cgi
1 #!/usr/local/bin/perl
2 # create_master.cgi
3 # Create a new master zone
4
5 require './bind8-lib.pl';
6 &ReadParse();
7 &error_setup($text{'mcreate_err'});
8 $access{'master'} || &error($text{'mcreate_ecannot'});
9 $access{'ro'} && &error($text{'master_ero'});
10 $conf = &get_config();
11 if ($in{'view'} ne '') {
12         $view = $conf->[$in{'view'}];
13         &can_edit_view($view) || &error($text{'master_eviewcannot'});
14         $vconf = $view->{'members'};
15         $viewname = $view->{'values'}->[0];
16         }
17 else {
18         $vconf = $conf;
19         $viewname = undef;
20         }
21
22 # validate inputs
23 if ($in{'rev'}) {
24         local($ipv4);
25         ($ipv4 = &check_net_ip($in{'zone'})) ||
26             $config{'support_aaaa'} &&
27             ($in{'zone'} =~ /^([\w:]+)(\/\d+)?$/ && &check_ip6address($1)) ||
28                 &error(&text('create_enet', $in{'zone'}));
29         if ($ipv4) {
30                 $in{'zone'} = &ip_to_arpa($in{'zone'});
31                 }
32         else {
33                 $in{'zone'} = &net_to_ip6int($1, ($2 ? substr($2, 1) : "" ));
34                 }
35         }
36 else {
37         ($in{'zone'} =~ /^[\d\.]+$/ || $in{'zone'} =~ /^[\d\:]+(\/[\d]+)?$/) &&
38                 &error(&text('create_edom2', $in{'zone'}));
39         &valdnsname($in{'zone'}, 0, ".") ||
40                 &error(&text('create_edom', $in{'zone'}));
41         }
42 $in{'zone'} =~ s/\.$//;
43 &valdnsname($in{'master'}, 0, ".") ||
44         &error(&text('master_emaster', $in{'master'}));
45 if ($in{'master'} !~ /\.$/) { $in{'master'} .= "."; }
46 &valemail($in{'email'}) || &valemail(&dotted_to_email($in{'email'})) ||
47         &error(&text('master_eemail', $in{'email'}));
48 $in{'email'} = &email_to_dotted($in{'email'});
49 $in{'refresh'} =~ /^\d+$/ ||
50         &error(&text('master_erefresh', $in{'refresh'}));
51 $in{'retry'} =~ /^\d+$/ ||
52         &error(&text('master_eretry', $in{'retry'}));
53 $in{'expiry'} =~ /^\d+$/ ||
54         &error(&text('master_eexpiry', $in{'expiry'}));
55 $in{'minimum'} =~ /^\d+$/ ||
56         &error(&text('master_eminimum', $in{'minimum'}));
57 $base = $access{'dir'} ne '/' ? $access{'dir'} :
58         $config{'master_dir'} ? $config{'master_dir'} :
59                                 &base_directory($conf);
60 $base =~ s/\/+$// if ($base ne '/');
61 if ($base !~ /^([a-z]:)?\//) {
62         # Master dir is relative .. make absolute
63         $base = &base_directory()."/".$base;
64         }
65 if ($in{'tmpl'}) {
66         for($i=0; $config{"tmpl_$i"}; $i++) {
67                 @c = split(/\s+/, $config{"tmpl_$i"}, 3);
68                 if ($c[1] eq 'A' && !$c[2] && !&check_ipaddress($in{'ip'})) {
69                         &error($text{'master_eip'});
70                         }
71                 }
72         }
73 foreach $z (&find("zone", $vconf)) {
74         if (lc($z->{'value'}) eq lc($in{'zone'})) {
75                 &error($text{'master_etaken'});
76                 }
77         }
78 if (!$in{'file_def'}) {
79         $in{'file'} =~ /^\S+$/ ||
80                 &error(&text('create_efile', $in{'file'}));
81         if ($in{'file'} !~ /^\//) {
82                 $in{'file'} = $base."/".$in{'file'};
83                 }
84         &allowed_zone_file(\%access, $in{'file'}) ||
85                 &error(&text('create_efile2', $in{'file'}));
86         }
87 else {
88         $in{'file'} = &automatic_filename($in{'zone'}, $in{'rev'}, $base,
89                                           $view ? $view->{'value'} : undef);
90         }
91 -r &make_chroot($in{'file'}) && &error(&text('create_efile4', $in{'file'}));
92 if ($in{'onslave'}) {
93         @mips = split(/\s+/, $in{'mip'});
94         @mips || &error($text{'master_emips'});
95         foreach $m (@mips) {
96                 &check_ipaddress($m) || &error(&text('master_emip', $m));
97                 }
98         }
99
100 # Create the zone file and initial records
101 &create_master_records($in{'file'}, $in{'zone'}, $in{'master'}, $in{'email'},
102                        $in{'refresh'}.$in{'refunit'},
103                        $in{'retry'}.$in{'retunit'},
104                        $in{'expiry'}.$in{'expunit'},
105                        $in{'minimum'}.$in{'minunit'},
106                        $in{'master_ns'},
107                        $in{'onslave'} && $access{'remote'},
108                        $in{'tmpl'}, $in{'ip'}, $in{'addrev'});
109
110 if ($config{'relative_paths'}) {
111         # Make path relative to BIND base directory
112         $bdir = &base_directory($conf);
113         $in{'file'} =~ s/^\Q$bdir\/\E//;
114         }
115
116 # create the zone directive
117 $dir = { 'name' => 'zone',
118          'values' => [ $in{'zone'} ],
119          'type' => 1,
120          'members' => [ { 'name' => 'type',
121                           'values' => [ 'master' ] },
122                         { 'name' => 'file',
123                           'values' => [ $in{'file'} ] } ]
124         };
125
126 # Add also-notify for slaves
127 if ($in{'onslave'}) {
128         @slaves = &list_slave_servers();
129         if (@slaves) {
130                 $also = { 'name' => 'also-notify',
131                           'type' => 1,
132                           'members' => [ ] };
133                 foreach $s (@slaves) {
134                         push(@{$also->{'members'}},
135                              { 'name' => &to_ipaddress($s->{'host'}) });
136                         }
137                 push(@{$dir->{'members'}}, $also);
138                 push(@{$dir->{'members'}}, { 'name' => 'notify',
139                                              'values' => [ 'yes' ] });
140                 }
141         }
142
143 # create the zone
144 &create_zone($dir, $conf, $in{'view'});
145 &set_ownership(&make_chroot($config{'named_conf'}));
146 &webmin_log("create", "master", $in{'zone'}, \%in);
147
148 &add_zone_access($in{'zone'});
149
150 # Get the new zone's index
151 $idx = &get_zone_index($in{'zone'}, $in{'view'});
152
153 # Create on slave servers
154 if ($in{'onslave'} && $access{'remote'}) {
155         @slaveerrs = &create_on_slaves($in{'zone'}, $mips[0],
156                         $in{'sfile_def'} == 1 ? "none" :
157                         $in{'sfile_def'} == 2 ? undef : $in{'sfile'},
158                         undef, $viewname);
159         if (@slaveerrs) {
160                 &error(&text('master_errslave',
161                      "<p>".join("<br>", map { "$_->[0]->{'host'} : $_->[1]" }
162                                             @slaveerrs)));
163                 }
164         }
165
166 &redirect("edit_master.cgi?index=$idx&view=$in{'view'}");
167
168