legacy.inc 11.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
<?php
/*
        Copyright (C) 2015 Deciso B.V.
        Copyright (C) 2009, 2010 Scott Ullrich
        Copyright (C) 2005 Colin Smith
        All rights reserved.

        Redistribution and use in source and binary forms, with or without
        modification, are permitted provided that the following conditions are met:

        1. Redistributions of source code must retain the above copyright notice,
           this list of conditions and the following disclaimer.

        2. Redistributions in binary form must reproduce the above copyright
           notice, this list of conditions and the following disclaimer in the
           documentation and/or other materials provided with the distribution.

        THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
        INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
        AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
        AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
        OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        POSSIBILITY OF SUCH DAMAGE.
*/

/**
 * request functions which may be registered by the xmlrpc system
 * @return array
 */
Ad Schellevis's avatar
Ad Schellevis committed
34
function xmlrpc_publishable_legacy()
35 36
{
    $publish = array(
37
        'filter_configure_xmlrpc','interfaces_carp_configure_xmlrpc',
38
        'backup_config_section_xmlrpc','restore_config_section_xmlrpc', 'merge_config_section_xmlrpc',
39
        'firmware_version_xmlrpc','reboot_xmlrpc','get_notices_xmlrpc'
40 41 42
    );


43
    return $publish;
44 45
}

46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
/*
 * does_vip_exist($vip): return true or false if a vip is
 * configured.
 */
function does_vip_exist($vip) {
	global $config;

	if(!$vip)
		return false;


	switch ($vip['mode']) {
	case "carp":
	case "ipalias":
		/* XXX: Make proper checks? */
		$realif = get_real_interface($vip['interface']);
		if (!does_interface_exist($realif)) {
			return false;
		}
		break;
	case "proxyarp":
		/* XXX: Implement this */
	default:
		return false;
	}

	$ifacedata = pfSense_getall_interface_addresses($realif);
	foreach ($ifacedata as $vipips) {
		if ($vipips == "{$vip['subnet']}/{$vip['subnet_bits']}")
			return true;
	}

	return false;
}

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
/*
	This function was borrowed from a comment on PHP.net at the following URL:
	http://www.php.net/manual/en/function.array-merge-recursive.php#73843
 */
function array_merge_recursive_unique($array0, $array1) {

	$arrays = func_get_args();
	$remains = $arrays;

	// We walk through each arrays and put value in the results (without
	// considering previous value).
	$result = array();

	// loop available array
	foreach($arrays as $array) {

		// The first remaining array is $array. We are processing it. So
		// we remove it from remaing arrays.
		array_shift($remains);

		// We don't care non array param, like array_merge since PHP 5.0.
		if(is_array($array)) {
			// Loop values
			foreach($array as $key => $value) {
				if(is_array($value)) {
					// we gather all remaining arrays that have such key available
					$args = array();
					foreach($remains as $remain) {
						if(array_key_exists($key, $remain)) {
							array_push($args, $remain[$key]);
						}
					}

					if(count($args) > 2) {
						// put the recursion
						$result[$key] = call_user_func_array(__FUNCTION__, $args);
					} else {
						foreach($value as $vkey => $vval) {
119 120 121
							if (!isset($result[$key]) || !is_array($result[$key])) {
								$result[$key] = array();
							}
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
							$result[$key][$vkey] = $vval;
						}
					}
				} else {
					// simply put the value
					$result[$key] = $value;
				}
			}
		}
	}
	return $result;
}



137

138
/**
139
 * @param null $category
140 141
 * @return mixed
 */
142
function get_notices_xmlrpc($category = null)
143
{
144 145 146 147 148
    if ($category==null) {
        return get_notices();
    } else {
        return get_notices($category);
    }
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168

}

/**
 * perform a system reboot
 * @return bool true
 */
function reboot_xmlrpc()
{
    mwexec_bg("/usr/local/etc/rc.reboot");

    return true;
}

/**
 * retrieve firmware version
 * @return mixed
 */
function firmware_version_xmlrpc()
{
169 170
    require_once("pfsense-utils.inc");

171
    return host_firmware_version();
172
}
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191

/**
 * interfaces_vips_configure
 * @return mixed
 */
function interfaces_carp_configure_xmlrpc()
{
    require_once("interfaces.inc");

    interfaces_vips_configure();
    return true;
}

/**
 * filter reconfigure
 * @return mixed
 */
function filter_configure_xmlrpc()
{
192
    global $config;
193
    require_once("filter.inc");
Ad Schellevis's avatar
Ad Schellevis committed
194
    require_once("system.inc");
195
    require_once("interfaces.inc");
196 197 198
    require_once("vslb.inc");
    require_once("openvpn.inc");
    require_once("services.inc");
199
    require_once("rrd.inc");
200
    require_once('pfsense-utils.inc');
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216

    filter_configure();
    system_routing_configure();
    setup_gateways_monitor();
    relayd_configure();
    openvpn_resync_all();
    if (isset($config['dnsmasq']['enable'])) {
        services_dnsmasq_configure();
    } elseif (isset($config['unbound']['enable'])) {
        services_unbound_configure();
    } else {
        # Both calls above run services_dhcpd_configure(), then we just
        # need to call it when them are not called to avoid restart dhcpd
        # twice, as described on ticket #3797
        services_dhcpd_configure();
    }
217
    system_hosts_generate();
218 219 220 221 222
    local_sync_accounts();

    return true;
}

223 224 225 226 227 228 229 230

/**
 * @param $confData array containing config data
 * @return bool
 */
function merge_config_section_xmlrpc($confData)
{
    global $config;
231
    $config_new = array_merge_recursive($config, $confData);
232 233 234 235 236 237 238 239 240 241 242 243 244 245
    $config = $config_new;
    $mergedkeys = implode(",", array_keys($confData));
    write_config(sprintf(gettext("Merged in config (%s sections) from XMLRPC client."), $mergedkeys));
    return true;
}

/**
 * restore config section
 * @param $new_config
 * @return bool
 */
function restore_config_section_xmlrpc($new_config)
{
    global $config;
246

247
    require_once("interfaces.inc");
248
    require_once("filter.inc");
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266

    // TODO: initial cleanup operation performed, but a full rewrite is probably a better plan.
    $old_config = $config;

    // 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', 'filter', 'nat', 'dhcpd', 'dhcpv6');
    $sync_full_done = array();
    foreach ($sync_full as $syncfull) {
        if (isset($new_config[$syncfull])) {
            $config[$syncfull] = $new_config[$syncfull];
            unset($new_config[$syncfull]);
            $sync_full_done[] = $syncfull;
        }
    }

    $vipbackup = array();
    $oldvips = array();
267 268 269 270 271 272 273 274
    if (isset($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']}";
            } elseif ($vip['mode'] == "ipalias" && (strstr($vip['interface'], "_vip") || strstr($vip['interface'], "lo0"))) {
                $oldvips[$vip['subnet']] = "{$vip['interface']}{$vip['subnet']}{$vip['subnet_bits']}";
            } elseif (($vip['mode'] == "ipalias" || $vip['mode'] == 'proxyarp') && !(strstr($vip['interface'], "_vip") || strstr($vip['interface'], "lo0"))) {
                $vipbackup[] = $vip;
275 276 277 278 279 280 281 282 283
            }
        }
    }

    // For vip section, first keep items sent from the master
    $config = array_merge_recursive_unique($config, $new_config);

    /* Then add ipalias and proxyarp types already defined on the backup */
    if (is_array($vipbackup) && !empty($vipbackup)) {
284
        if (!isset($config['virtualip'])) {
285 286
            $config['virtualip'] = array();
        }
287
        if (!isset($config['virtualip']['vip'])) {
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
            $config['virtualip']['vip'] = array();
        }
        foreach ($vipbackup as $vip) {
            array_unshift($config['virtualip']['vip'], $vip);
        }

    }

    /* Log what happened */
    $mergedkeys = implode(",", array_merge(array_keys($new_config), $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
     */
304
    if (isset($new_config['virtualip']['vip'])) {
305 306
        $carp_setuped = false;
        $anyproxyarp = false;
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
        if (isset($config['virtualip']['vip'])) {
          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) {
                          $carp_setuped = true;
                      }
                      interface_carp_configure($vip);
                      break;
              }
          }
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
        }
        if ($carp_setuped) {
            interfaces_carp_setup();
        }

        if ($anyproxyarp) {
            interface_proxyarp_configure();
        }

    }

    if (isset($old_config['ipsec']['enable']) !== isset($config['ipsec']['enable'])) {
        vpn_ipsec_configure();
    }


    unset($old_config);

    return true;
}
362 363 364 365 366 367 368 369

/**
 * @param $sectionKeys
 * @return array config data
 */
function backup_config_section_xmlrpc($sectionKeys)
{
    global $config;
370 371
    if (!is_array($sectionKeys)) {
        // single item
372
        return array_intersect_key($config, array($sectionKeys => 0));
373 374 375 376
    } else {
        // backup more sections at once
        return array_intersect_key($config, array_flip($sectionKeys));
    }
377
}