Handle hostnames with upper-case letters
[webmin.git] / net / united-linux-lib.pl
1 # united-linux-lib.pl
2 # Networking functions for united linux
3
4 $net_scripts_dir = "/etc/sysconfig/network";
5 $routes_config = "/etc/sysconfig/network/routes";
6 $sysctl_config = "/etc/sysconfig/sysctl";
7
8 do 'linux-lib.pl';
9
10 # boot_interfaces()
11 # Returns a list of interfaces brought up at boot time
12 sub boot_interfaces
13 {
14 local(@rv, $f);
15 opendir(CONF, &translate_filename($net_scripts_dir));
16 while($f = readdir(CONF)) {
17         next if ($f !~ /^ifcfg-([a-z0-9:\.]+)$/);
18         local (%conf, $b);
19         $b->{'fullname'} = $1;
20         &read_env_file("$net_scripts_dir/$f", \%conf);
21         if ($b->{'fullname'} =~ /(\S+):(\d+)/) {
22                 $b->{'name'} = $1;
23                 $b->{'virtual'} = $2;
24                 }
25         else { $b->{'name'} = $b->{'fullname'}; }
26         $b->{'up'} = ($conf{'STARTMODE'} eq 'onboot');
27         local $pfx;
28         if ($conf{'IPADDR'} =~ /^(\S+)\/(\d+)$/) {
29                 $b->{'address'} = $1;
30                 $pfx = $2;
31                 }
32         else {
33                 $b->{'address'} = $conf{'IPADDR'};
34                 }
35         $pfx = $conf{'PREFIXLEN'} if (!$pfx);
36         if ($pfx) {
37                 $b->{'netmask'} = &prefix_to_mask($pfx);
38                 }
39         else {
40                 $b->{'netmask'} = $conf{'NETMASK'};
41                 }
42         $b->{'broadcast'} = $conf{'BROADCAST'};
43         $b->{'dhcp'} = ($conf{'BOOTPROTO'} eq 'dhcp');
44         $b->{'edit'} = ($b->{'name'} !~ /^ppp|irlan/);
45         $b->{'index'} = scalar(@rv);
46         $b->{'file'} = "$net_scripts_dir/$f";
47         push(@rv, $b);
48         }
49 closedir(CONF);
50 return @rv;
51 }
52
53 # save_interface(&details)
54 # Create or update a boot-time interface
55 sub save_interface
56 {
57 local(%conf);
58 local $name = $_[0]->{'virtual'} ne "" ? $_[0]->{'name'}.":".$_[0]->{'virtual'}
59                                        : $_[0]->{'name'};
60 &lock_file("$net_scripts_dir/ifcfg-$name");
61 &read_env_file("$net_scripts_dir/ifcfg-$name", \%conf);
62 $conf{'IPADDR'} = $_[0]->{'address'};
63 local($ip1, $ip2, $ip3, $ip4) = split(/\./, $_[0]->{'address'});
64 $conf{'NETMASK'} = $_[0]->{'netmask'};
65 local($nm1, $nm2, $nm3, $nm4) = split(/\./, $_[0]->{'netmask'});
66 if ($_[0]->{'address'} && $_[0]->{'netmask'}) {
67         $conf{'NETWORK'} = sprintf "%d.%d.%d.%d",
68                                 ($ip1 & int($nm1))&0xff,
69                                 ($ip2 & int($nm2))&0xff,
70                                 ($ip3 & int($nm3))&0xff,
71                                 ($ip4 & int($nm4))&0xff;
72         }
73 else {
74         $conf{'NETWORK'} = '';
75         }
76 delete($conf{'PREFIXLEN'});
77 $conf{'BROADCAST'} = $_[0]->{'broadcast'};
78 $conf{'STARTMODE'} = $_[0]->{'up'} ? "onboot" :
79                      $conf{'STARTMODE'} eq "onboot" ? "manual" :
80                                                       $conf{'STARTMODE'};
81 $conf{'BOOTPROTO'} = $_[0]->{'dhcp'} ? "dhcp" : "static";
82 $conf{'UNIQUE'} = time();
83 &write_env_file("$net_scripts_dir/ifcfg-$name", \%conf);
84 &unlock_file("$net_scripts_dir/ifcfg-$name");
85 }
86
87 # delete_interface(&details)
88 # Delete a boot-time interface
89 sub delete_interface
90 {
91 local $name = $_[0]->{'virtual'} ne "" ? $_[0]->{'name'}.":".$_[0]->{'virtual'}
92                                        : $_[0]->{'name'};
93 &unlink_logged("$net_scripts_dir/ifcfg-$name");
94 }
95
96 # can_edit(what)
97 # Can some boot-time interface parameter be edited?
98 sub can_edit
99 {
100 return $_[0] ne "mtu" && $_[0] ne "bootp";
101 }
102
103 # valid_boot_address(address)
104 # Is some address valid for a bootup interface
105 sub valid_boot_address
106 {
107 return &check_ipaddress($_[0]);
108 }
109
110 # get_hostname()
111 sub get_hostname
112 {
113 local %conf;
114 &read_env_file($network_config, \%conf);
115 if ($conf{'HOSTNAME'}) {
116         return $conf{'HOSTNAME'};
117         }
118 return &get_system_hostname(1);
119 }
120
121 # save_hostname(name)
122 sub save_hostname
123 {
124 local %conf;
125 &system_logged("hostname $_[0] >/dev/null 2>&1");
126 &open_lock_tempfile(HOST, ">/etc/HOSTNAME");
127 &print_tempfile(HOST, $_[0],"\n");
128 &close_tempfile(HOST);
129 &lock_file($network_config);
130 &read_env_file($network_config, \%conf);
131 $conf{'HOSTNAME'} = $_[0];
132 &write_env_file($network_config, \%conf);
133 &unlock_file($network_config);
134 undef(@main::get_system_hostname);      # clear cache
135 }
136
137 # get_domainname()
138 sub get_domainname
139 {
140 local $d;
141 &execute_command("domainname", undef, \$d, undef);
142 chop($d);
143 return $d;
144 }
145
146 # save_domainname(domain)
147 sub save_domainname
148 {
149 local %conf;
150 &execute_command("domainname ".quotemeta($_[0]));
151 &read_env_file($network_config, \%conf);
152 if ($_[0]) {
153         $conf{'NISDOMAIN'} = $_[0];
154         }
155 else {
156         delete($conf{'NISDOMAIN'});
157         }
158 &write_env_file($network_config, \%conf);
159 }
160
161 sub routing_config_files
162 {
163 return ( $routes_config, $sysctl_config );
164 }
165
166 sub routing_input
167 {
168 local (@routes, $i);
169 &open_readfile(ROUTES, $routes_config);
170 while(<ROUTES>) {
171         s/#.*$//;
172         s/\r|\n//g;
173         local @r = map { $_ eq '-' ? undef : $_ } split(/\s+/, $_);
174         push(@routes, \@r) if (@r);
175         }
176 close(ROUTES);
177
178 # show default router and device
179 local ($def) = grep { $_->[0] eq "default" } @routes;
180 print &ui_table_row($text{'routes_default'},
181         &ui_opt_textbox("gateway", $def->[1], 15, $text{'routes_none'}));
182
183 print &ui_table_row($text{'routes_device2'},
184         &ui_opt_textbox("gatewaydev", $def->[3], 6, $text{'routes_none'}));
185
186 # Forwarding enabled?
187 &read_env_file($sysctl_config, \%sysctl);
188 print &ui_table_row($text{'routes_forward'},
189         &ui_yesno_radio("forward", $sysctl{'IP_FORWARD'} eq 'yes'));
190
191 # show static network routes
192 my $i = 0;
193 my @table;
194 foreach my $r (@routes, [ ]) {
195         next if ($r eq $def);
196         push(@table, [ &ui_textbox("dev_$i", $r->[3], 6),
197                        &ui_textbox("net_$i", $r->[0], 15),
198                        &ui_textbox("netmask_$i", $r->[2], 15),
199                        &ui_textbox("gw_$i", $r->[1], 15),
200                        &ui_textbox("type_$i", $r->[4], 10) ]);
201         }
202 print &ui_table_row($text{'routes_static'},         &ui_columns_table([ $text{'routes_ifc'}, $text{'routes_net'},
203                             $text{'routes_mask'}, $text{'routes_gateway'},
204                             $text{'routes_type'} ],
205                           undef, \@table, undef, 1));
206 }
207
208 sub parse_routing
209 {
210 # Parse route inputs
211 local (@routes, $r, $i);
212 if (!$in{'gateway_def'}) {
213         &to_ipaddress($in{'gateway'}) ||
214                 &error(&text('routes_edefault', $in{'gateway'}));
215         local @def = ( "default", $in{'gateway'}, undef, undef );
216         if (!$in{'gatewaydev_def'}) {
217                 $in{'gatewaydev'} =~ /^\S+$/ ||
218                         &error(&text('routes_edevice', $in{'gatewaydev'}));
219                 $def[3] = $in{'gatewaydev'};
220                 }
221         push(@routes, \@def);
222         }
223 for($i=0; defined($in{"dev_$i"}); $i++) {
224         next if (!$in{"net_$i"});
225         &check_ipaddress($in{"net_$i"}) ||
226                 $in{"net_$i"} =~ /^(\S+)\/(\d+)$/ && &check_ipaddress($1) ||
227                 &error(&text('routes_enet', $in{"net_$i"}));
228         $in{"dev_$i"} =~ /^\S*$/ || &error(&text('routes_edevice', $dev));
229         !$in{"netmask_$i"} || &check_ipaddress($in{"netmask_$i"}) ||
230                 &error(&text('routes_emask', $in{"netmask_$i"}));
231         !$in{"gw_$i"} || &check_ipaddress($in{"gw_$i"}) ||
232                 &error(&text('routes_egateway', $in{"gw_$i"}));
233         $in{"type_$i"} =~ /^\S*$/ ||
234                 &error(&text('routes_etype', $in{"type_$i"}));
235         push(@routes, [ $in{"net_$i"}, $in{"gw_$i"}, $in{"netmask_$i"},
236                         $in{"dev_$i"}, $in{"type_$i"} ] );
237         }
238
239 # Save routes and routing option
240 &open_tempfile(ROUTES, ">$routes_config");
241 foreach $r (@routes) {
242         &print_tempfile(ROUTES,join(" ", map { $_ eq '' ? "-" : $_ } @$r),"\n");
243         }
244 &close_tempfile(ROUTES);
245 local $lref = &read_file_lines($sysctl_config);
246 for($i=0; $i<@$lref; $i++) {
247         if ($lref->[$i] =~ /^\s*IP_FORWARD\s*=/) {
248                 $lref->[$i] = "IP_FORWARD=".($in{'forward'} ? "yes" : "no");
249                 }
250         }
251 &flush_file_lines();
252 }
253
254 sub os_feedback_files
255 {
256 opendir(DIR, $net_scripts_dir);
257 local @f = readdir(DIR);
258 closedir(DIR);
259 return ( (map { "$net_scripts_dir/$_" } grep { /^ifcfg-/ } @f),
260          $network_config, $static_route_config, "/etc/resolv.conf",
261          "/etc/nsswitch.conf", "/etc/HOSTNAME" );
262 }
263
264 # apply_network()
265 # Apply the interface and routing settings
266 sub apply_network
267 {
268 &system_logged("(cd / ; /etc/init.d/network stop ; /etc/init.d/network start) >/dev/null 2>&1");
269 }
270
271 # supports_address6([&iface])
272 # Returns 1 if managing IPv6 interfaces is supported
273 sub supports_address6
274 {
275 local ($iface) = @_;
276 return 0;
277 }
278
279 1;
280