virtual_ip, add optional vhid to support alias ip's on carp. for https://github.com/opnsense/core/issues/1779

This commit is contained in:
Ad Schellevis 2017-08-24 22:49:04 +02:00
parent 733118ae91
commit 8ae34afbba
3 changed files with 31 additions and 30 deletions

View File

@ -1825,7 +1825,8 @@ function interface_ipalias_configure(&$vip)
if (is_ipaddrv6($vip['subnet'])) {
$af = "inet6";
}
mwexec("/sbin/ifconfig " . escapeshellarg($if) ." {$af} ". escapeshellarg($vip['subnet']) ."/" . escapeshellarg($vip['subnet_bits']) . " alias");
$vhid = !empty($vip['vhid']) ? "vhid " . escapeshellarg($vip['vhid']) : "";
mwexec("/sbin/ifconfig " . escapeshellarg($if) ." {$af} ". escapeshellarg($vip['subnet']) ."/" . escapeshellarg($vip['subnet_bits']) . " alias ". $vhid);
}
function interface_carp_configure(&$vip)

View File

@ -85,31 +85,6 @@ function deleteVIPEntry($id) {
}
}
if ($a_vip[$id]['mode'] == "ipalias") {
$subnet = gen_subnet($a_vip[$id]['subnet'], $a_vip[$id]['subnet_bits']) . "/" . $a_vip[$id]['subnet_bits'];
$found_if = false;
$found_carp = false;
$found_other_alias = false;
if ($subnet == $if_subnet)
$found_if = true;
$vipiface = $a_vip[$id]['interface'];
foreach ($a_vip as $vip_id => $vip) {
if ($vip_id != $id) {
if ($vip['interface'] == $vipiface && ip_in_subnet($vip['subnet'], $subnet)) {
if ($vip['mode'] == "carp") {
$found_carp = true;
} else if ($vip['mode'] == "ipalias") {
$found_other_alias = true;
}
}
}
}
if ($found_carp === true && $found_other_alias === false && $found_if === false) {
$input_errors[] = sprintf(gettext("This entry cannot be deleted because it is still referenced by a CARP IP with the description %s."), $vip['descr']);
}
}
if (count($input_errors) == 0) {
// Special case since every proxyarp vip is handled by the same daemon.
if ($a_vip[$id]['mode'] == "proxyarp") {

View File

@ -63,7 +63,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$configId = $id;
}
$pconfig = array();
$pconfig['vhid'] = find_last_used_vhid() + 1;
$form_fields = array('mode', 'vhid', 'advskew', 'advbase', 'password', 'subnet', 'subnet_bits'
, 'descr' ,'type', 'interface' );
@ -140,9 +139,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
if ($pconfig['mode'] == 'carp') {
/* verify against reusage of vhids */
foreach($config['virtualip']['vip'] as $vipId => $vip) {
if(isset($vip['vhid']) && $vip['vhid'] == $pconfig['vhid'] && $vip['interface'] == $pconfig['interface'] && $vipId <> $id) {
$input_errors[] = sprintf(gettext("VHID %s is already in use on interface %s. Pick a unique number on this interface."),$pconfig['vhid'], convert_friendly_interface_to_friendly_descr($pconfig['interface']));
}
if (isset($vip['vhid']) && $vip['vhid'] == $pconfig['vhid'] && $vip['interface'] == $pconfig['interface'] && $vipId <> $id) {
$input_errors[] = sprintf(gettext("VHID %s is already in use on interface %s. Pick a unique number on this interface."),$pconfig['vhid'], convert_friendly_interface_to_friendly_descr($pconfig['interface']));
}
}
if (empty($pconfig['password'])) {
$input_errors[] = gettext("You must specify a CARP password that is shared between the two VHID members.");
@ -153,6 +152,16 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
}
} else if ($pconfig['mode'] != 'ipalias' && $pconfig['interface'] == "lo0") {
$input_errors[] = gettext("For this type of vip localhost is not allowed.");
} elseif ($pconfig['mode'] == 'ipalias' && !empty($pconfig['vhid'])) {
$carpvip_found = false;
foreach($config['virtualip']['vip'] as $vipId => $vip) {
if ($vip['interface'] == $pconfig['interface'] && $vip['vhid'] == $pconfig['vhid'] && $vip['mode'] == 'carp') {
$carpvip_found = true ;
}
}
if (!$carpvip_found) {
$input_errors[] = sprintf(gettext("VHID %s should be defined on interface %s."),$pconfig['vhid'], convert_friendly_interface_to_friendly_descr($pconfig['interface']));
}
}
}
@ -237,10 +246,12 @@ $( document ).ready(function() {
$("#advbase").attr('disabled', true);
$("#noexpand").attr('disabled', true);
$("#noexpandrow").addClass("hidden");
$("#vhid_none").attr('disabled', false);
switch ($(this).val()) {
case "ipalias":
$("#type").prop("selectedIndex",0);
$("#vhid").attr('disabled', false);
$("#subnet_bits").attr('disabled', false);
$("#typenote").html("<?=gettext("Please provide a single IP address.");?>");
break;
@ -251,6 +262,10 @@ $( document ).ready(function() {
$("#vhid").attr('disabled', false);
$("#advskew").attr('disabled', false);
$("#advbase").attr('disabled', false);
$("#vhid_none").attr('disabled', true);
if ($("#vhid").val() == null) {
$("#max_vhid").click();
}
$("#typenote").html("<?=gettext("This must be the network's subnet mask. It does not specify a CIDR range.");?>");
break;
case "proxyarp":
@ -272,6 +287,12 @@ $( document ).ready(function() {
}, 100);
});
$("#max_vhid").click(function(event){
event.preventDefault();
$("#vhid").val($(this).data('vhid'));
$("#vhid").selectpicker('refresh');
});
// toggle initial mode change
$("#mode").change();
@ -393,12 +414,16 @@ $( document ).ready(function() {
<td><a id="help_for_vhid" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("VHID Group");?></td>
<td>
<select id='vhid' name='vhid' class="selectpicker" data-size="10" data-width="auto">
<option value="" id="vhid_none"> </option>
<?php for ($i = 1; $i <= 255; $i++): ?>
<option value="<?=$i;?>" <?= $i == $pconfig['vhid'] ? "selected=\"selected\"" : ""; ?>>
<?=$i;?>
</option>
<?php endfor; ?>
</select>
<button data-vhid="<?=find_last_used_vhid() + 1;?>" id="max_vhid" class="btn btn-default btn-cs">
<?=gettext("Unused");?>
</button>
<div class="hidden" for="help_for_vhid">
<?=gettext("Enter the VHID group that the machines will share.");?>
</div>