Server IP : 195.201.23.43 / Your IP : 3.144.40.81 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 : |
# Functions for setting up a virtual IP interface # setup_virt(&domain) # Bring up an interface for a domain, if the IP isn't already enabled sub setup_virt { local ($d) = @_; &obtain_lock_virt($d); &foreign_require("net"); local @active = &net::active_interfaces(); if (!$d->{'virtalready'}) { # Actually bring up &$first_print(&text('setup_virt', $d->{'ip'})); local ($iface) = grep { $_->{'fullname'} eq $config{'iface'} } @active; if (!$iface) { # Interface doesn't really exist! &$second_print(&text('setup_virtmissing', $config{'iface'})); return 0; } local $b; local $vmin = $config{'iface_base'} || int($net::min_virtual_number); local $vmax = -1; foreach $b (@active) { $vmax = $b->{'virtual'} if ($b->{'virtual'} ne '' && $b->{'name'} eq $iface->{'name'} && $b->{'virtual'} > $vmax); } local $vwant = $vmax + 1; if ($vwant < $vmin) { $vwant = $vmin; } local $netmask = $d->{'netmask'} || $net::virtual_netmask || $iface->{'netmask'}; local $virt = { 'address' => $d->{'ip'}, 'netmask' => $netmask, 'broadcast' => &net::compute_broadcast($d->{'ip'}, $netmask), 'name' => $iface->{'name'}, 'virtual' => $vwant, 'up' => 1, 'desc' => "Virtualmin server $d->{'dom'}", }; $virt->{'fullname'} = $virt->{'name'}.":".$virt->{'virtual'}; &net::save_interface($virt); if (&auto_apply_interface()) { &net::apply_network(); } else { &net::activate_interface($virt); } $d->{'iface'} = $virt->{'fullname'}; &$second_print(&text('setup_virtdone', $d->{'iface'})); } else { # Just guess the interface &$first_print(&text('setup_virt2', $d->{'ip'})); local ($virt) = grep { $_->{'address'} eq $d->{'ip'} } @active; $d->{'iface'} = $virt ? $virt->{'fullname'} : undef; if ($d->{'iface'}) { &$second_print(&text('setup_virtdone2', $d->{'iface'})); } else { &$second_print(&text('setup_virtnotdone', $d->{'ip'})); } } &build_local_ip_list(); &release_lock_virt($d); ®ister_post_action(\&restart_bind) if ($config{'dns'}); return 1; } # delete_virt(&domain) # Take down the network interface for a domain sub delete_virt { local ($d) = @_; if (!$d->{'virtalready'}) { &$first_print($text{'delete_virt'}); &obtain_lock_virt($d); &foreign_require("net"); local ($biface) = grep { $_->{'address'} eq $d->{'ip'} } &net::boot_interfaces(); local ($aiface) = grep { $_->{'address'} eq $d->{'ip'} } &net::active_interfaces(); if (!$biface) { &$second_print(&text('delete_noiface', $d->{'iface'})); } elsif ($biface->{'virtual'} ne '') { &net::delete_interface($biface); if (&auto_apply_interface()) { &net::apply_network(); } elsif ($aiface && $aiface->{'virtual'} ne '') { &net::deactivate_interface($aiface) } &$second_print($text{'setup_done'}); } else { &$second_print(&text('delete_novirt', $biface->{'fullname'})); } &build_local_ip_list(); &release_lock_virt($d); } delete($d->{'iface'}); return 1; } # modify_virt(&domain, &old) # Change the virtual IP address for a domain sub modify_virt { local ($d, $oldd) = @_; if ($d->{'ip'} ne $oldd->{'ip'} && $d->{'virt'} && !$d->{'virtalready'}) { # Change IP on virtual interface &$first_print($text{'save_virt'}); &obtain_lock_virt($d); &foreign_require("net"); local ($biface) = grep { $_->{'address'} eq $oldd->{'ip'} } &net::boot_interfaces(); local ($aiface) = grep { $_->{'address'} eq $oldd->{'ip'} } &net::active_interfaces(); if ($biface) { if ($biface->{'virtual'} ne '') { $biface->{'address'} = $d->{'ip'}; &net::save_interface($biface); } if (&auto_apply_interface()) { &net::apply_network(); } elsif ($aiface->{'virtual'} ne '') { $aiface->{'address'} = $d->{'ip'}; &net::activate_interface($aiface); } &$second_print($text{'setup_done'}); } else { &$second_print(&text('delete_novirt', $oldd->{'iface'})); } &build_local_ip_list(); &release_lock_virt($d); ®ister_post_action(\&restart_bind) if ($config{'dns'}); } } # clone_virt(&domain, &old-domain) # No need to do anything here, as an IP address doesn't have any settings that # need copying sub clone_virt { return 1; } # validate_virt(&domain) # Check for boot-time and active network interfaces sub validate_virt { local ($d) = @_; if (!$_[0]->{'virtalready'}) { # Only check boot-time interface if added by Virtualmin local @boots = &bootup_ip_addresses(); if (&indexof($d->{'ip'}, @boots) < 0) { return &text('validate_evirtb', $d->{'ip'}); } } local @acts = &active_ip_addresses(); if (&indexof($d->{'ip'}, @acts) < 0) { return &text('validate_evirta', $d->{'ip'}); } return undef; } # check_virt_clash(ip) # Returns 1 if some IP is already in use, 0 if not sub check_virt_clash { # Check active and boot-time interfaces local %allips = &interface_ip_addresses(); return 1 if ($allips{$_[0]}); # Do a quick ping test local $pingcmd = $gconfig{'os_type'} =~ /-linux$/ ? "ping -c 1 -t 1" : "ping"; local ($out, $timed_out) = &backquote_with_timeout( $pingcmd." ".$_[0]." 2>&1", 2, 1); return 1 if (!$timed_out && !$?); return 0; } # virtual_ip_input(&templates, [reseller-name-list], [show-original], # [default-mode]) # Returns HTML for selecting a virtual IP mode for a new server, or not sub virtual_ip_input { local ($tmpls, $resel, $orig, $mode) = @_; $mode ||= 0; local $defip = &get_default_ip($resel); local ($t, $anyalloc, $anychoose, $anyzone); if (&running_in_zone() || &running_in_vserver()) { # When running in a Solaris zone or VServer, you MUST select an # existing active IP, as they are controlled from the host. $anyzone = 1; } elsif (&can_use_feature("virt")) { # Check if private IPs are allocated or manual, if we are # allowed to choose them. foreach $t (@$tmpls) { local $tmpl = &get_template($t->{'id'}); if ($tmpl->{'ranges'} ne "none") { $anyalloc++; } else { $anychoose++; } } } local @opts; if ($orig) { # For restores - option to use original IP push(@opts, [ -1, $text{'form_origip'} ]); } push(@opts, [ 0, &text('form_shared', $defip) ]); local @shared = sort { $a cmp $b } &list_shared_ips(); if (@shared && &can_edit_sharedips()) { # Can select from extra shared list push(@opts, [ 3, $text{'form_shared2'}, &ui_select("sharedip", undef, [ map { [ $_ ] } @shared ]) ]); } if ($anyalloc) { # Can allocate push(@opts, [ 2, &text('form_alloc') ]); } if ($anychoose) { # Can enter arbitrary IP push(@opts, [ 1, $text{'form_vip'}, &ui_textbox("ip", undef, 20)." ". &ui_checkbox("virtalready", 1, $text{'form_virtalready'}) ]); } if ($anyzone) { # Can select an existing active IP &foreign_require("net"); local @act = grep { $_->{'virtual'} ne '' } &net::active_interfaces(); if (@act) { push(@opts, [ 4, $text{'form_activeip'}, &ui_select("zoneip", undef, [ map { [ $_->{'address'} ] } @act ]) ]); } else { push(@opts, [ 4, $text{'form_activeip'}, &ui_textbox("zoneip", undef, 20) ]); } } if ($mode == 5 && $anyalloc) { # Use shared or allocated (for restores only) push(@opts, [ 5, &text('form_allocmaybe') ]); } my %hasmodes = map { $_->[0], 1 } @opts; if (!$hasmodes{$mode}) { # Mode is not on the list .. use shared mode or none $mode = $hasmodes{0} ? 0 : -2; } return &ui_radio_table("virt", $mode, \@opts, 1); } # parse_virtual_ip(&template, reseller) # Parses the virtual IP input field, and returns the IP to use, virt flag, # already flag and netmask. May call &error if the input is invalid. sub parse_virtual_ip { local ($tmpl, $resel) = @_; if ($in{'virt'} == 2) { # Automatic IP allocation chosen .. select one from either the # reseller's range, or the template if ($resel) { # Creating by or under a reseller .. use his range, if any foreach my $r (split(/\s+/, $resel)) { local %acl = &get_reseller_acl($r); if ($acl{'ranges'}) { local ($ip, $netmask) = &free_ip_address(\%acl); $ip || &error(&text('setup_evirtalloc')); return ($ip, 1, 0, $netmask); } } } $tmpl->{'ranges'} ne "none" || &error(&text('setup_evirttmpl')); local ($ip, $netmask) = &free_ip_address($tmpl); $ip || &error(&text('setup_evirtalloc')); return ($ip, 1, 0, $netmask); } elsif ($in{'virt'} == 1) { # Manual IP allocation chosen $tmpl->{'ranges'} eq "none" || &error(&text('setup_evirttmpl2')); &check_ipaddress($in{'ip'}) || &error($text{'setup_eip'}); local $clash = &check_virt_clash($in{'ip'}); if ($in{'virtalready'}) { # Fail if the IP isn't yet active, or if claimed by another # virtual server $clash || &error(&text('setup_evirtclash2', $in{'ip'})); local $already = &get_domain_by("ip", $in{'ip'}); $already && &error(&text('setup_evirtclash4', $already->{'dom'})); } else { # Fail if the IP *is* already active $clash && &error(&text('setup_evirtclash')); } return ($in{'ip'}, 1, $in{'virtalready'}); } elsif ($in{'virt'} == 3 && &can_edit_sharedips()) { # On a shared virtual IP &indexof($in{'sharedip'}, &list_shared_ips()) >= 0 || &error(&text('setup_evirtnoshared')); return ($in{'sharedip'}, 0, 0); } elsif ($in{'virt'} == 4 && (&running_in_zone() || &running_in_vserver())) { # On an active IP on a virtual machine that cannot bring up its # own IP. &check_ipaddress($in{'zoneip'}) || &error($text{'setup_eip'}); local $clash = &check_virt_clash($in{'zoneip'}); $clash || &error(&text('setup_evirtclash2', $in{'zoneip'})); local $already = &get_domain_by("ip", $in{'ip'}); $already && &error(&text('setup_evirtclash4', $already->{'dom'})); return ($in{'zoneip'}, 1, 1); } elsif ($in{'virt'} == 5) { # Allocate if needed, shared otherwise local ($ip, $netmask) = &free_ip_address($tmpl); return ($ip, 1, 0, $netmask); } else { # Global shared IP local $defip = &get_default_ip($resel); return ($defip, 0, 0); } } # show_template_virt(&tmpl) # Outputs HTML for editing virtual IP related template options sub show_template_virt { local ($tmpl) = @_; # IP allocation ranges (v4 and possibly v6) foreach my $ranges ("ranges", &supports_ip6() ? ( "ranges6" ) : ( )) { local @ranges; @ranges = &parse_ip_ranges($tmpl->{$ranges}) if ($tmpl->{$ranges} ne "none"); local @rfields = map { ($ranges."_start_".$_, $ranges."_end_".$_) } (0..scalar(@ranges)+1); local $rtable = &none_def_input($ranges, $tmpl->{$ranges}, $text{'tmpl_rangesbelow'}, 0, 0, undef, \@rfields); local @table; local $i = 0; local $s = $ranges eq "ranges" ? 20 : 6; foreach my $r (@ranges, [ ], [ ]) { push(@table, [ &ui_textbox($ranges."_start_$i", $r->[0], 20), &ui_textbox($ranges."_end_$i", $r->[1], 20), &ui_opt_textbox($ranges."_mask_$i", $r->[2], $s, $text{'default'}) ]); $i++; } $rtable .= &ui_columns_table( [ $text{'tmpl_ranges_start'}, $text{'tmpl_ranges_end'}, $text{'tmpl_ranges_mask'} ], undef, \@table, undef, 1); print &ui_table_row(&hlink($text{'tmpl_'.$ranges}, "template_".$ranges."_mode"), $rtable); } } # parse_template_virt(&tmpl) # Updates virtual IP related template options from %in sub parse_template_virt { local ($tmpl) = @_; # Save IPv4 and possibly v6 allocation ranges foreach my $ranges ("ranges", &supports_ip6() ? ( "ranges6" ) : ( )) { if ($in{$ranges.'_mode'} == 0) { $tmpl->{$ranges} = "none"; } elsif ($in{$ranges.'_mode'} == 1) { $tmpl->{$ranges} = undef; } else { local (@ranges, $start, $end); for(my $i=0; defined($start = $in{$ranges."_start_$i"}); $i++) { next if (!$start); $end = $in{$ranges."_end_$i"}; $mask = $in{$ranges."_mask_${i}_def"} ? undef : $in{$ranges."_mask_$i"}; if ($ranges eq "ranges") { # IPv4 verification &check_ipaddress($start) || &error(&text('tmpl_eranges_start', $start)); &check_ipaddress($end) || &error(&text('tmpl_eranges_end', $start)); local @start = split(/\./, $start); local @end = split(/\./, $end); $start[0] == $end[0] && $start[1] == $end[1] && $start[2] == $end[2] || &error(&text('tmpl_eranges_net', $start)); $start[3] <= $end[3] || &error(&text('tmpl_eranges_lower', $start)); !$mask || &check_ipaddress($mask) || &error(&text('tmpl_eranges_mask', $start)); } else { # v6 verification &check_ip6address($start) || &error(&text('tmpl_eranges6_start',$start)); &check_ip6address($end) || &error(&text('tmpl_eranges6_end', $end)); !$mask || $mask =~ /^\d+$/ || &error(&text('tmpl_eranges_mask', $start)); } push(@ranges, [ $start, $end, $mask ]); } @ranges || &error($text{'tmpl_e'.$ranges}); $tmpl->{$ranges} = &join_ip_ranges(\@ranges); } } } # build_local_ip_list() # Create a local cache file of IPs on this system sub build_local_ip_list { &foreign_require("net"); &open_lock_tempfile(IPCACHE, ">$module_config_directory/localips"); foreach my $a (&net::active_interfaces()) { if ($a->{'address'}) { &print_tempfile(IPCACHE, $a->{'address'},"\n"); } } &close_tempfile(IPCACHE); } # obtain_lock_virt(&domain) # Signal that we are locking virtual IPs sub obtain_lock_virt { # Lock the network config directory or file &obtain_lock_anything(); if ($main::got_lock_virt == 0) { &foreign_require("net"); $main::got_lock_virt_file = $net::network_interfaces_config || $net::network_config || "$module_config_directory/virtlock"; &lock_file($main::got_lock_virt_file); if (&supports_ip6()) { # Also lock file for IPv6 $main::got_lock_virt6_file = &ip6_interfaces_file(); &lock_file($main::got_lock_virt6_file) if ($main::got_lock_virt6_file); } } $main::got_lock_virt++; } # Release virtual IPs lock sub release_lock_virt { # Unlock the network config directory or file if ($main::got_lock_virt == 1) { &unlock_file($main::got_lock_virt6_file) if ($main::got_lock_virt6_file); &unlock_file($main::got_lock_virt_file); } $main::got_lock_virt-- if ($main::got_lock_virt); &release_lock_anything(); } # can_reset_virt(&domain) # Resetting the virtual IP is a bad idea, as it could cause re-allocation sub can_reset_virt { return 0; } # auto_apply_interface() # Returns 1 if changes should only be made to the boot-time interface config, # and then applied sub auto_apply_interface { &foreign_require("net"); return $net::net_mode eq "nm"; } $done_feature_script{'virt'} = 1; 1;Private