Handle hostnames with upper-case letters
[webmin.git] / bind8 / slave_add.cgi
1 #!/usr/local/bin/perl
2 # Add or update a server or group from the webmin servers module
3
4 require './bind8-lib.pl';
5 $access{'slaves'} || &error($text{'slaves_ecannot'});
6 &ReadParse();
7 &foreign_require("servers", "servers-lib.pl");
8 @allservers = grep { $_->{'user'} } &servers::list_servers();
9
10 if ($in{'server'} =~ /^group_(\S+)/) {
11         # Add all from a group
12         ($group) = grep { $_->{'name'} eq $1 }
13                         &servers::list_all_groups(\@allservers);
14         foreach $m (@{$group->{'members'}}) {
15                 push(@add, grep { $_->{'host'} eq $m } @allservers);
16                 }
17         &error_setup($text{'add_gerr'});
18         $msg = &text('add_gmsg', $group->{'name'});
19         $in{'name_def'} || &error($text{'add_egname'});
20         }
21 else {
22         # Add a single host
23         @add = grep { $_->{'id'} eq $in{'server'} } @allservers;
24         &error_setup($text{'add_err'});
25         $msg = &text('add_msg', &server_name($add[0]));
26         $in{'name_def'} || &valdnsname($in{'name'}) ||
27                 &error($text{'add_ename'});
28         }
29 $in{'view_def'} || $in{'view'} =~ /\S/ || &error($text{'add_eview'});
30 $myip = $config{'this_ip'} || &to_ipaddress(&get_system_hostname());
31 $myip && $myip ne "127.0.0.1" ||
32         &error($text{'add_emyip'});
33
34 &ui_print_header(undef, $text{'add_title'}, "");
35 print "<b>$msg</b><p>\n";
36
37 # Setup error handler for down hosts
38 sub add_error
39 {
40 $add_error_msg = join("", @_);
41 }
42 &remote_error_setup(\&add_error);
43
44 # Build map from zone names to configs
45 $conf = &get_config();
46 %zmap = ( );
47 @zoneconfs = &find("zone", $conf);
48 foreach $v (@views) {
49         push(@zoneconfs, &find("zone", $v->{'members'}));
50         }
51 foreach $z (@zoneconfs) {
52         $type = &find_value("type", $z->{'members'});
53         if ($type eq "master") {
54                 $zmap{$z->{'value'}} = $z;
55                 }
56         }
57
58 # Make sure each host is set up for BIND
59 @zones = grep { $_->{'type'} eq 'master' } &list_zone_names();
60 foreach $s (@add) {
61         $s->{'bind8_view'} = $in{'view_def'} == 1 ? undef :
62                              $in{'view_def'} == 2 ? "*" : $in{'view'};
63         $add_error_msg = undef;
64         local $bind8 = &remote_foreign_check($s, "bind8");
65         if ($add_error_msg) {
66                 print "$add_error_msg<p>\n";
67                 next;
68                 }
69         if (!$bind8) {
70                 print &text('add_echeck', $s->{'host'}),"<p>\n";
71                 next;
72                 }
73         &remote_foreign_require($s, "bind8", "bind8-lib.pl");
74         local $inst = &remote_foreign_call($s, "bind8",
75                                            "foreign_installed", "bind8", 1);
76         if (!$inst) {
77                 print &text('add_emissing', $s->{'host'}),"<p>\n";
78                 next;
79                 }
80
81         # Check for needed Webmin versions
82         local $rver = &remote_foreign_call($s, "bind8", "get_webmin_version");
83         if ($rver < 1.202) {
84                 print &text('add_eversion', $s->{'host'}, 1.202),"<p>\n";
85                 next;
86                 }
87         if ($s->{'bind8_view'} && $s->{'bind8_view'} =~ /\s/ &&
88             $rver < 1.422) {
89                 print &text('add_eversion2', $s->{'host'}, 1.422),"<p>\n";
90                 next;
91                 }
92
93         # Check for non-IP name
94         if (&check_ipaddress($s->{'host'}) && $in{'name_def'}) {
95                 print &text('add_eipaddr', $s->{'host'}),"<p>\n";
96                 next;
97                 }
98         if (!$in{'name_def'} && &check_ipaddress($in{'name'})) {
99                 print &text('add_eipaddr', $s->{'host'}),"<p>\n";
100                 next;
101                 }
102
103         @rzones = grep { $_->{'type'} ne 'view' }
104                        &remote_foreign_call($s, "bind8", "list_zone_names");
105         print &text('add_ok', $s->{'host'}, scalar(@rzones)),"<p>\n";
106         $s->{'sec'} = $in{'sec'};
107         $s->{'nsname'} = $in{'name_def'} ? undef : $in{'name'};
108         &add_slave_server($s);
109         %rgot = map { $_->{'name'}, 1 } @rzones;
110
111         if ($in{'sync'}) {
112                 # Add all master zones from this server to the slave
113                 $zcount = 0;
114                 $zerr = 0;
115                 $sip = &to_ipaddress($s->{'host'});
116                 foreach $zone (grep { !$rgot{$_->{'name'}} } @zones) {
117                         ($slaveerr) = &create_on_slaves($zone->{'name'}, $myip,
118                                 undef, [ $s->{'host'} ], $zone->{'view'});
119                         if ($slaveerr) {
120                                 $zerrs{$slaveerr->[0]->{'host'}} ||=
121                                         $slaveerr->[1];
122                                 $zerr++;
123                                 }
124                         else {
125                                 $zcount++;
126                                 }
127                         }
128
129                 # Restart the slave
130                 if ($zcount) {
131                         &remote_foreign_call($s, "bind8", "restart_bind");
132                         }
133
134                 # Add slave IP to master zone allow-transfer and also-notify
135                 # blocks
136                 $dchanged = 0;
137                 foreach $zone (@zones) {
138                         $z = $zmap{$zone->{'name'}};
139                         next if (!$z || !$sip);
140                         foreach $d ("also-notify", "allow-transfer") {
141                                 $n = &find($d, $z->{'members'});
142                                 next if (!$n);
143                                 ($got) = grep { $_->{'name'} eq $sip }
144                                               @{$n->{'members'}};
145                                 next if ($got);
146                                 push(@{$n->{'members'}}, { 'name' => $sip });
147                                 &lock_file($z->{'file'});
148                                 &save_directive($z, $d, [ $n ], 1);
149                                 &flush_file_lines($z->{'file'});
150                                 $dchanged++;
151                                 }
152                         }
153                 if ($dchanged) {
154                         &unlock_all_files();
155                         &restart_bind();
156                         }
157
158                 # Tell the user
159                 if ($zerr) {
160                         print &text('add_createerr', $s->{'host'},
161                                     $zcount, $zerr),"<br>\n";
162                         foreach $k (keys %zerrs) {
163                                 print "$k : $zerrs{$k}<br>\n";
164                                 }
165                         print "<p>\n";
166                         }
167                 else {
168                         print &text('add_createok', $s->{'host'},
169                                     $zcount),"<p>\n";
170                         }
171                 }
172         }
173 &remote_finished();
174 if ($in{'add'}) {
175         &webmin_log("add", "host", $add[0]->{'host'});
176         }
177 else {
178         &webmin_log("add", "group", $group->{'name'});
179         }
180
181 &ui_print_footer("list_slaves.cgi", $text{'slaves_return'});
182