/** * Loads configuration information from an INI file. * @param $type The type of configuration information to load: e.g., actions, relationships, valuelists, fields, etc.. * @param $tablename The name of the table for which to load the configuration information. * @return Associative array of configuration options in the same form as they would be returned by parse_ini_file(). */ function &loadConfigFromINI($type = null, $tablename = '__global__') { if (!isset($tablename)) { $tablename = '__global__'; } $app =& Dataface_Application::getInstance(); if ($type == 'lang') { if (isset($this->config[$type][$app->_conf['lang']][$tablename])) { return $this->config[$type][$app->_conf['lang']][$tablename]; } } else { if (isset($this->config[$type][$tablename])) { return $this->config[$type][$tablename]; } } $app =& Dataface_Application::getInstance(); $paths = array(); $lpaths = array(); if ($type === 'lang') { if ($tablename !== '__global__') { if (!class_exists('Dataface_Table')) { import('Dataface/Table.php'); } $lpaths[] = Dataface_Table::getBasePath($tablename) . '/tables/' . basename($tablename) . '/lang/' . basename($app->_conf['lang']) . '.ini'; } else { $paths[] = DATAFACE_PATH . '/lang/' . basename($app->_conf['lang']) . '.ini'; $lpaths[] = DATAFACE_SITE_PATH . '/lang/' . basename($app->_conf['lang']) . '.ini'; } } else { if ($tablename !== '__global__') { //$paths = array(DATAFACE_SITE_PATH.'/tables/'.$tablename.'/'.$type.'.ini'); // Valuelists handle their own cascading because it involves loading // the valuelist each time... and there may be opportunities to // share between tables if ($type != 'valuelists') { $paths[] = DATAFACE_PATH . '/' . basename($type) . '.ini'; } if ($type != 'valuelists') { $lpaths[] = DATAFACE_SITE_PATH . '/' . basename($type) . '.ini'; } $lpaths[] = Dataface_Table::getBasePath($tablename) . '/tables/' . basename($tablename) . '/' . basename($type) . '.ini'; } else { $paths[] = DATAFACE_PATH . '/' . basename($type) . '.ini'; $lpaths[] = DATAFACE_SITE_PATH . '/' . basename($type) . '.ini'; } } // Add the ability to override settings in a module. // Added Feb. 28, 2007 by Steve Hannah for version 0.6.14 if (isset($app->_conf['_modules']) and count($app->_conf['_modules']) > 0) { foreach ($app->_conf['_modules'] as $classname => $path) { $modpath = explode('_', $classname); array_shift($modpath); $modname = implode('_', $modpath); if ($type == 'lang') { $paths[] = DATAFACE_SITE_PATH . '/modules/' . basename($modname) . '/lang/' . basename($app->_conf['lang']) . '.ini'; $paths[] = DATAFACE_PATH . '/modules/' . basename($modname) . '/lang/' . basename($app->_conf['lang']) . '.ini'; } else { $paths[] = DATAFACE_SITE_PATH . '/modules/' . basename($modname) . '/' . basename($type) . '.ini'; $paths[] = DATAFACE_PATH . '/modules/' . basename($modname) . '/' . basename($type) . '.ini'; } } } // Add the ability to override settings in the database. // Added Feb. 27, 2007 by Steve Hannah for version 0.6.14 if (@$app->_conf['enable_db_config'] and $type != 'permissions') { if ($type == 'lang') { if (isset($tablename)) { $lpaths[] = 'db:tables/' . basename($tablename) . '/lang/' . basename($app->_conf['lang']); } else { $paths[] = 'db:lang/' . basename($app->_conf['lang']) . '.ini'; } } else { if (isset($tablename)) { $paths[] = 'db:' . basename($type) . '.ini'; $lpaths[] = 'db:tables/' . basename($tablename) . '/' . basename($type) . '.ini'; } else { $paths[] = 'db:' . basename($type) . '.ini'; } } } if (!$tablename) { $tablename = '__global__'; } $paths = array_merge($paths, $lpaths); //print_r($paths); //print_r($lpaths); if (!isset($this->config[$type][$tablename])) { $this->config[$type][$tablename] = array(); } //import('Config.php'); foreach ($paths as $path) { if (!isset($this->iniLoaded[$path])) { $this->iniLoaded[$path] = true; if (is_readable($path) || strstr($path, 'db:') == $path) { $config = $this->parse_ini_file($path, true); if (isset($config['charset']) and function_exists('iconv')) { I18Nv2::recursiveIconv($config, $config['charset'], 'UTF-8'); } if (isset($config['__extends__'])) { $config = array_merge_recursive_unique($this->loadConfigFromINI($type, $config['__extends__']), $config); } $this->rawConfig[$path] =& $config; } else { $config = array(); $this->rawConfig[$path] =& $config; } } else { //echo "getting $path from raw config."; //echo "$path already loaded:".implode(',', array_keys($this->iniLoaded)); $config =& $this->rawConfig[$path]; } //echo "Conf for x".$path."x: "; if (!$config) { $config = array(); } foreach (array_keys($config) as $entry) { if ($type == 'lang') { $this->config[$type][$app->_conf['lang']][$tablename][$entry] =& $config[$entry]; } else { $sep = null; if (strpos($entry, '>') !== false) { $sep = '>'; } if (strpos($entry, ' extends ') !== false) { $sep = ' extends '; } if ($sep and is_array($config[$entry])) { list($newentry, $entryParents) = explode($sep, $entry); $entryParents = array_map('trim', explode(',', $entryParents)); $newentry = trim($newentry); $cout = array(); foreach ($entryParents as $entryParent) { if (!isset($this->config[$type][$tablename][$entryParent])) { throw new Exception("Illegal extends. Parent not found: " . $entryParent . " from rule: " . $entry . " in " . $path); } $pconf =& $this->config[$type][$tablename][$entryParent]; if (!is_array($pconf)) { throw new Exception("Illegal extends. Parent is not a section. It is a scalar: " . $entryParent . " from rule: " . $entry . " in " . $path); } foreach ($pconf as $pkey => $pval) { $cout[$pkey] = $pval; } unset($pconf); } $centry =& $config[$entry]; foreach ($centry as $ckey => $cval) { $cout[$ckey] = $cval; } unset($centry); unset($this->config[$type][$tablename][$entry]); unset($this->config[$type][$tablename][$newentry]); $this->config[$type][$tablename][$newentry] =& $cout; unset($cout); //$this->config[$type][$tablename][trim($newentry)] = array_merge($this->config[$type][$tablename][trim($entryParent)],$config[$entry]); } else { $this->config[$type][$tablename][$entry] =& $config[$entry]; } } } unset($config); } // New in 2.1. We load user config if it is available to override the // built-in config $user_config = $this->userConfig; $upaths = array(); if ($type == 'lang') { $upaths[] = 'lang/' . $app->_conf['lang'] . '.ini'; $upaths[] = 'tables/' . $tablename . '/lang/' . $app->_conf['lang'] . '.ini'; } else { $upaths[] = $type . '.ini'; $upaths[] = 'tables/' . $tablename . '/' . $type . '.ini'; } foreach ($upaths as $p) { if (isset($user_config->{$p})) { if ($type == 'lang') { $this->config[$type][$app->_conf['lang']][$tablename] = array_merge_recursive_unique($this->config[$type][$app->_conf['lang']][$tablename], $this->objectToArray($user_config->{$p})); } else { $this->config[$type][$tablename] = array_merge_recursive_unique($this->config[$type][$tablename], $this->objectToArray($user_config->{$p})); } } } if ($type == 'lang') { return $this->config[$type][$app->_conf['lang']][$tablename]; } else { return $this->config[$type][$tablename]; } }
function &getFieldgroups() { if (!isset($this->_cache[__FUNCTION__])) { $fg =& $this->_fieldgroups; $parent =& $this->getParent(); if (isset($parent)) { $fg = array_merge_recursive_unique($parent->getFieldgroups(), $fg); uasort($fg, array(&$this, '_compareFields')); } $this->_cache[__FUNCTION__] =& $fg; } return $this->_cache[__FUNCTION__]; }
function restore_config_section_xmlrpc($raw_params) { global $config, $xmlrpc_g; $old_config = $config; $old_ipsec_enabled = ipsec_enabled(); if (xmlrpc_loop_detect()) { log_error("Disallowing CARP sync loop"); return; } $params = xmlrpc_params_to_php($raw_params); if (!xmlrpc_auth($params)) { xmlrpc_authfail(); return $xmlrpc_g['return']['authfail']; } /* * Make sure it doesn't end up with both dnsmasq and unbound enabled * simultaneously in secondary * */ if (isset($params[0]['unbound']['enable']) && isset($config['dnsmasq']['enable'])) { unset($config['dnsmasq']['enable']); services_dnsmasq_configure(); } else { if (isset($params[0]['dnsmasq']['enable']) && isset($config['unbound']['enable'])) { unset($config['unbound']['enable']); services_unbound_configure(); } } // Some sections should just be copied and not merged or we end // up unable to sync the deletion of the last item in a section $sync_full = array('dnsmasq', 'unbound', 'ipsec', 'aliases', 'wol', 'load_balancer', 'openvpn', 'cert', 'ca', 'crl', 'schedules', 'filter', 'nat', 'dhcpd', 'dhcpv6'); $sync_full_done = array(); foreach ($sync_full as $syncfull) { if (isset($params[0][$syncfull])) { $config[$syncfull] = $params[0][$syncfull]; unset($params[0][$syncfull]); $sync_full_done[] = $syncfull; } } $vipbackup = array(); $oldvips = array(); if (isset($params[0]['virtualip'])) { if (is_array($config['virtualip']['vip'])) { foreach ($config['virtualip']['vip'] as $vipindex => $vip) { if ($vip['mode'] == "carp") { $oldvips["{$vip['interface']}_vip{$vip['vhid']}"]['content'] = "{$vip['password']}{$vip['advskew']}{$vip['subnet']}{$vip['subnet_bits']}{$vip['advbase']}"; $oldvips["{$vip['interface']}_vip{$vip['vhid']}"]['interface'] = $vip['interface']; $oldvips["{$vip['interface']}_vip{$vip['vhid']}"]['subnet'] = $vip['subnet']; } else { if ($vip['mode'] == "ipalias" && (substr($vip['interface'], 0, 4) == '_vip' || strpos($vip['interface'], "lo0"))) { $oldvips[$vip['subnet']]['content'] = "{$vip['interface']}{$vip['subnet']}{$vip['subnet_bits']}"; $oldvips[$vip['subnet']]['interface'] = $vip['interface']; $oldvips[$vip['subnet']]['subnet'] = $vip['subnet']; } else { if (($vip['mode'] == "ipalias" || $vip['mode'] == 'proxyarp') && !(substr($vip['interface'], 0, 4) == '_vip') || strpos($vip['interface'], "lo0")) { $vipbackup[] = $vip; } } } } } } // For vip section, first keep items sent from the master $config = array_merge_recursive_unique($config, $params[0]); /* Then add ipalias and proxyarp types already defined on the backup */ if (is_array($vipbackup) && !empty($vipbackup)) { if (!is_array($config['virtualip'])) { $config['virtualip'] = array(); } if (!is_array($config['virtualip']['vip'])) { $config['virtualip']['vip'] = array(); } foreach ($vipbackup as $vip) { array_unshift($config['virtualip']['vip'], $vip); } } /* Log what happened */ $mergedkeys = implode(",", array_merge(array_keys($params[0]), $sync_full_done)); write_config(sprintf(gettext("Merged in config (%s sections) from XMLRPC client."), $mergedkeys)); /* * The real work on handling the vips specially * This is a copy of intefaces_vips_configure with addition of not reloading existing/not changed carps */ if (isset($params[0]['virtualip']) && is_array($config['virtualip']) && is_array($config['virtualip']['vip'])) { $carp_setuped = false; $anyproxyarp = false; foreach ($config['virtualip']['vip'] as $vip) { if ($vip['mode'] == "carp" && isset($oldvips["{$vip['interface']}_vip{$vip['vhid']}"])) { if ($oldvips["{$vip['interface']}_vip{$vip['vhid']}"]['content'] == "{$vip['password']}{$vip['advskew']}{$vip['subnet']}{$vip['subnet_bits']}{$vip['advbase']}") { if (does_vip_exist($vip)) { unset($oldvips["{$vip['interface']}_vip{$vip['vhid']}"]); continue; // Skip reconfiguring this vips since nothing has changed. } } } else { if ($vip['mode'] == "ipalias" && strstr($vip['interface'], "_vip") && isset($oldvips[$vip['subnet']])) { if ($oldvips[$vip['subnet']]['content'] == "{$vip['interface']}{$vip['subnet']}{$vip['subnet_bits']}") { if (does_vip_exist($vip)) { unset($oldvips[$vip['subnet']]); continue; // Skip reconfiguring this vips since nothing has changed. } } unset($oldvips[$vip['subnet']]); } } switch ($vip['mode']) { case "proxyarp": $anyproxyarp = true; break; case "ipalias": interface_ipalias_configure($vip); break; case "carp": if ($carp_setuped == false) { $carp_setuped = true; } interface_carp_configure($vip); break; } } /* Cleanup remaining old carps */ foreach ($oldvips as $oldvipar) { $oldvipif = get_real_interface($oldvipar['interface']); if (!empty($oldvipif)) { if (is_ipaddrv6($oldvipar['subnet'])) { mwexec("/sbin/ifconfig " . escapeshellarg($oldvipif) . " inet6 " . escapeshellarg($oldvipar['subnet']) . " delete"); } else { pfSense_interface_deladdress($oldvipif, $oldvipar['subnet']); } } } if ($carp_setuped == true) { interfaces_sync_setup(); } if ($anyproxyarp == true) { interface_proxyarp_configure(); } } if ($old_ipsec_enabled !== ipsec_enabled()) { vpn_ipsec_configure(); } unset($old_config); return $xmlrpc_g['return']['true']; }
/** * Returns the field definition for a field in the relationship. * @param string $fieldname The field name. This can be absolute or * relative. (e.g. Absolute would be something like people.firstName, * whereas relative would be something like firstName). * @returns array or null if field doesn't exist. */ function &getField($fieldname, $with_override = true) { if (!isset($this->_cache[__FUNCTION__][$fieldname][$with_override ? 0 : 1])) { if (strpos($fieldname, '.') !== false) { list($tablename, $sfieldname) = explode('.', $fieldname); $table =& Dataface_Table::loadTable($tablename); $field =& $table->getField($sfieldname); } else { // Check the domain table first $domainTable = Dataface_Table::loadTable($this->getDomainTable()); $f =& $domainTable->getField($fieldname); if (!PEAR::isError($f)) { $field =& $f; } else { // Domain table doesn't have a field by this name $fields = preg_grep('/\\.' . preg_quote($fieldname, '/') . '$/', $this->fields(true)); if (count($fields) > 0) { $lfieldname = reset($fields); list($tablename, $sfieldname) = explode('.', $lfieldname); $table =& Dataface_Table::loadTable($tablename); $field =& $table->getField($sfieldname); } else { $field = null; } } } if (isset($field) and $with_override and isset($this->_field_def_overrides[$field['name']])) { $field_merged = array_merge_recursive_unique($field, $this->_field_def_overrides[$field['name']]); unset($field); $field =& $field_merged; } $this->_cache[__FUNCTION__][$fieldname][$with_override ? 0 : 1] =& $field; } return $this->_cache[__FUNCTION__][$fieldname][$with_override ? 0 : 1]; }
/** * Returns actions associated with this record. * @param $params An associative array of parameters for the actions to be retrieved. * Possible keys include: * category => the name of the category for the actions. */ function getActions($params = array()) { $params['record'] =& $this; $actions = $this->_table->getActions($params); $parent =& $this->getParentRecord(); if (isset($parent)) { $actions = array_merge_recursive_unique($parent->getActions($params), $actions); } return $actions; }
/** * Restore defined config section into local config * * @param string $username * @param string $password * @param array $sections * * @return bool */ public function restore_config_section($username, $password, $sections) { $this->auth($username, $password); global $config; $old_config = $config; $old_ipsec_enabled = ipsec_enabled(); if ($this->loop_detected) { log_error("Disallowing CARP sync loop"); return true; } /* * Some sections should just be copied and not merged or we end * up unable to sync the deletion of the last item in a section */ $sync_full_sections = array('aliases', 'ca', 'cert', 'crl', 'dhcpd', 'dhcpv6', 'dnsmasq', 'filter', 'ipsec', 'load_balancer', 'nat', 'openvpn', 'schedules', 'unbound', 'wol'); $syncd_full_sections = array(); foreach ($sync_full_sections as $section) { if (!isset($sections[$section])) { continue; } $config[$section] = $sections[$section]; unset($sections[$section]); $syncd_full_sections[] = $section; } $vipbackup = array(); $oldvips = array(); if (isset($sections['virtualip']) && is_array($config['virtualip']['vip'])) { foreach ($config['virtualip']['vip'] as $vip) { if ($vip['mode'] == "carp") { $key = $vip['interface'] . "_vip" . $vip['vhid']; $oldvips[$key]['content'] = $vip['password'] . $vip['advskew'] . $vip['subnet'] . $vip['subnet_bits'] . $vip['advbase']; $oldvips[$key]['interface'] = $vip['interface']; $oldvips[$key]['subnet'] = $vip['subnet']; } else { if ($vip['mode'] == "ipalias" && (substr($vip['interface'], 0, 4) == '_vip' || strstr($vip['interface'], "lo0"))) { $oldvips[$vip['subnet']]['content'] = $vip['interface'] . $vip['subnet'] . $vip['subnet_bits']; $oldvips[$vip['subnet']]['interface'] = $vip['interface']; $oldvips[$vip['subnet']]['subnet'] = $vip['subnet']; } else { if (($vip['mode'] == "ipalias" || $vip['mode'] == 'proxyarp') && !(substr($vip['interface'], 0, 4) == '_vip') || strstr($vip['interface'], "lo0")) { $vipbackup[] = $vip; } } } } } /* For vip section, first keep items sent from the master */ $config = array_merge_recursive_unique($config, $sections); /* * Then add ipalias and proxyarp types already defined * on the backup */ if (is_array($vipbackup) && !empty($vipbackup)) { if (!is_array($config['virtualip'])) { $config['virtualip'] = array(); } if (!is_array($config['virtualip']['vip'])) { $config['virtualip']['vip'] = array(); } foreach ($vipbackup as $vip) { array_unshift($config['virtualip']['vip'], $vip); } } /* Log what happened */ $mergedkeys = implode(",", array_merge(array_keys($sections), $syncd_full_sections)); write_config(sprintf(gettext("Merged in config (%s sections) from XMLRPC client."), $mergedkeys)); /* * The real work on handling the vips specially * This is a copy of intefaces_vips_configure with addition of * not reloading existing/not changed carps */ if (isset($sections['virtualip']) && is_array($config['virtualip']) && is_array($config['virtualip']['vip'])) { $carp_setuped = false; $anyproxyarp = false; foreach ($config['virtualip']['vip'] as $vip) { $key = "{$vip['interface']}_vip{$vip['vhid']}"; if ($vip['mode'] == "carp" && isset($oldvips[$key])) { if ($oldvips[$key]['content'] == $vip['password'] . $vip['advskew'] . $vip['subnet'] . $vip['subnet_bits'] . $vip['advbase'] && does_vip_exist($vip)) { unset($oldvips[$key]); /* * Skip reconfiguring this vips * since nothing has changed. */ continue; } } elseif ($vip['mode'] == "ipalias" && strstr($vip['interface'], "_vip") && isset($oldvips[$vip['subnet']])) { $key = $vip['subnet']; if ($oldvips[$key]['content'] == $vip['interface'] . $vip['subnet'] . $vip['subnet_bits'] && does_vip_exist($vip)) { unset($oldvips[$key]); /* * Skip reconfiguring this vips * since nothing has changed. */ continue; } unset($oldvips[$key]); } switch ($vip['mode']) { case "proxyarp": $anyproxyarp = true; break; case "ipalias": interface_ipalias_configure($vip); break; case "carp": $carp_setuped = true; interface_carp_configure($vip); break; } } /* Cleanup remaining old carps */ foreach ($oldvips as $oldvipar) { $oldvipif = get_real_interface($oldvipar['interface']); if (empty($oldvipif)) { continue; } if (is_ipaddrv6($oldvipar['subnet'])) { mwexec("/sbin/ifconfig " . escapeshellarg($oldvipif) . " inet6 " . escapeshellarg($oldvipar['subnet']) . " delete"); } else { pfSense_interface_deladdress($oldvipif, $oldvipar['subnet']); } } if ($carp_setuped == true) { interfaces_sync_setup(); } if ($anyproxyarp == true) { interface_proxyarp_configure(); } } if ($old_ipsec_enabled !== ipsec_enabled()) { vpn_ipsec_configure(); } unset($old_config); return true; }
/** * Get the links associate array as defined by the links.ini file. * * * Experimental... - * Should look a bit like * [local_col_name] => "related_tablename:related_col_name" * * * @return array|null * array = if there are links defined for this table. * empty array - if there is a links.ini file, but no links on this table * null - if no links.ini exists for this database (hence try auto_links). * @access public * @see DB_DataObject2::getLinks(), DB_DataObject2::getLink() */ function links() { if (empty(DB_DataObject2::$CONFIG)) { $this->_loadConfig(); } // have to connect.. -> otherwise things break later. $this->_connect(); if (isset(DB_DataObject2::$LINKS[$this->_database][$this->__table])) { return DB_DataObject2::$LINKS[$this->_database][$this->__table]; } // attempt to load links file here.. if (!isset(DB_DataObject2::$LINKS[$this->_database])) { if (isset(DB_DataObject2::$CONFIG["links_{$this->_database}"])) { $schemas = is_array(DB_DataObject2::$CONFIG["links_{$this->_database}"]) ? DB_DataObject2::$CONFIG["links_{$this->_database}"] : explode(PATH_SEPARATOR, DB_DataObject2::$CONFIG["links_{$this->_database}"]); } else { if (isset(DB_DataObject2::$CONFIG['schema_location'])) { if (is_array(DB_DataObject2::$CONFIG['schema_location'])) { $schema_locations = DB_DataObject2::$CONFIG['schema_location']; } else { $schema_locations = array(DB_DataObject2::$CONFIG['schema_location']); } } else { $schema_locations = array(); } $schemas = array(); foreach ($schema_locations as $schema_location) { $schemas[] = $schema_location . DIRECTORY_SEPARATOR . $this->_database . ".ini"; } } foreach ($schemas as $ini) { $links = str_replace('.ini', '.links.ini', $ini); if (file_exists($links) && is_file($links)) { /* not sure why $links = ... here - TODO check if that works */ if (!isset(DB_DataObject2::$LINKS[$this->_database])) { DB_DataObject2::$LINKS[$this->_database] = array(); } $new = parse_ini_file($links, true); DB_DataObject2::$LINKS[$this->_database] = array_merge_recursive_unique(DB_DataObject2::$LINKS[$this->_database], $new); if (!empty(DB_DataObject2::$CONFIG['debug'])) { $this->debug("Loaded links.ini file: {$links}", "links", 1); } } else { if (!empty(DB_DataObject2::$CONFIG['debug'])) { $this->debug("Missing links.ini file: {$links}", "links", 1); } } } } // if there is no link data at all on the file! // we return null. if (!isset(DB_DataObject2::$LINKS[$this->_database])) { return null; } if (isset(DB_DataObject2::$LINKS[$this->_database][$this->__table])) { return DB_DataObject2::$LINKS[$this->_database][$this->__table]; } return array(); }
function merge_config_section_xmlrpc($raw_params) { global $config, $xmlrpc_g; $params = xmlrpc_params_to_php($raw_params); if (!xmlrpc_auth($params)) { return $xmlrpc_g['return']['authfail']; } $config = array_merge_recursive_unique($config, $params[0]); $mergedkeys = implode(",", array_keys($params[0])); write_config("Merged in config ({$mergedkeys} sections) from XMLRPC client."); return $xmlrpc_g['return']['true']; }
function restore_config_section_xmlrpc($raw_params) { global $config, $xmlrpc_g; $params = xmlrpc_params_to_php($raw_params); if (!xmlrpc_auth($params)) { xmlrpc_authfail(); return $xmlrpc_g['return']['authfail']; } // Some sections should just be copied and not merged or we end // up unable to sync the deletion of the last item in a section $sync_full = array('ipsec', 'aliases', 'wol', 'load_balancer', 'openvpn', 'cert', 'ca', 'crl', 'schedules'); $sync_full_done = array(); foreach ($sync_full as $syncfull) { if (isset($params[0][$syncfull])) { $config[$syncfull] = $params[0][$syncfull]; unset($params[0][$syncfull]); $sync_full_done[] = $syncfull; } } $vipbackup = array(); $oldvips = array(); if (isset($params[0]['virtualip'])) { if (is_array($config['virtualip']['vip'])) { foreach ($config['virtualip']['vip'] as $vipindex => $vip) { if ($vip['mode'] == "carp") { $oldvips["{$vip['interface']}_vip{$vip['vhid']}"] = "{$vip['password']}{$vip['advskew']}{$vip['subnet']}{$vip['subnet_bits']}{$vip['advbase']}"; } else { if ($vip['mode'] == "ipalias" && strstr($vip['interface'], "_vip")) { $oldvips[$vip['subnet']] = "{$vip['interface']}{$vip['subnet']}{$vip['subnet_bits']}"; } else { if (($vip['mode'] == "ipalias" || $vip['mode'] == 'proxyarp') && !strstr($vip['interface'], "_vip")) { $vipbackup[] = $vip; } } } } } } // For vip section, first keep items sent from the master $config = array_merge_recursive_unique($config, $params[0]); /* Then add ipalias and proxyarp types already defined on the backup */ if (is_array($vipbackup) && !empty($vipbackup)) { if (!is_array($config['virtualip'])) { $config['virtualip'] = array(); } if (!is_array($config['virtualip']['vip'])) { $config['virtualip']['vip'] = array(); } foreach ($vipbackup as $vip) { array_unshift($config['virtualip']['vip'], $vip); } } /* Log what happened */ $mergedkeys = implode(",", array_merge(array_keys($params[0]), $sync_full_done)); write_config(sprintf(gettext("Merged in config (%s sections) from XMLRPC client."), $mergedkeys)); /* * The real work on handling the vips specially * This is a copy of intefaces_vips_configure with addition of not reloading existing/not changed carps */ if (isset($params[0]['virtualip']) && is_array($config['virtualip']) && is_array($config['virtualip']['vip'])) { $carp_setuped = false; $anyproxyarp = false; foreach ($config['virtualip']['vip'] as $vip) { if ($vip['mode'] == "carp" && isset($oldvips["{$vip['interface']}_vip{$vip['vhid']}"])) { if ($oldvips["{$vip['interface']}_vip{$vip['vhid']}"] == "{$vip['password']}{$vip['advskew']}{$vip['subnet']}{$vip['subnet_bits']}{$vip['advbase']}") { if (does_vip_exist($vip)) { unset($oldvips["{$vip['interface']}_vip{$vip['vhid']}"]); continue; // Skip reconfiguring this vips since nothing has changed. } } unset($oldvips["{$vip['interface']}_vip{$vip['vhid']}"]); } else { if ($vip['mode'] == "ipalias" && strstr($vip['interface'], "_vip") && isset($oldvips[$vip['subnet']])) { if ($oldvips[$vip['subnet']] = "{$vip['interface']}{$vip['subnet']}{$vip['subnet_bits']}") { if (does_vip_exist($vip)) { unset($oldvips[$vip['subnet']]); continue; // Skip reconfiguring this vips since nothing has changed. } } unset($oldvips[$vip['subnet']]); } } switch ($vip['mode']) { case "proxyarp": $anyproxyarp = true; break; case "ipalias": interface_ipalias_configure(&$vip); break; case "carp": if ($carp_setuped == false) { $carp_setuped = true; } interface_carp_configure($vip); break; case "carpdev-dhcp": interface_carpdev_configure($vip); break; } } /* Cleanup remaining old carps */ foreach ($oldvips as $oldvipif => $oldvippar) { if (!is_ipaddr($oldvipif) && does_interface_exist($oldvipif)) { pfSense_interface_destroy($oldvipif); } } if ($carp_setuped == true) { interfaces_carp_setup(); } if ($anyproxyarp == true) { interface_proxyarp_configure(); } } return $xmlrpc_g['return']['true']; }