#!/usr/local/bin/php-cgi -q . * 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. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgment: * "This product includes software developed by the pfSense Project * for use in the pfSense® software distribution. (http://www.pfsense.org/). * * 4. The names "pfSense" and "pfSense Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * coreteam@pfsense.org. * * 5. Products derived from this software may not be called "pfSense" * nor may "pfSense" appear in their names without prior written * permission of the Electric Sheep Fencing, LLC. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * * "This product includes software developed by the pfSense Project * for use in the pfSense software distribution (http://www.pfsense.org/). * * THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY * EXPRESSED 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 pfSense PROJECT OR * ITS CONTRIBUTORS 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. */ $options = getopt("hn", array("dry-run", "help")); if (isset($options["h"]) || isset($options["help"])) { echo "usage: /etc/rc.initial.setlanip [option ...]\n"; echo " -h, --help show this message\n"; echo " -n, --dry-run do not make any configuration changes\n"; return 0; } $dry_run = isset($options["n"]) || isset($options["dry-run"]); if ($dry_run) { echo "DRY RUN MODE IS ON\n"; } /* parse the configuration and include all functions used below */ require_once("config.inc"); require_once("functions.inc"); require_once("filter.inc"); require_once("shaper.inc"); require_once("rrd.inc"); function console_prompt_for_yn ($prompt_text) { global $fp; $good_answer = false; do { echo "\n" . $prompt_text . " (y/n) "; $yn = strtolower(chop(fgets($fp))); if (($yn == "y") || ($yn == "yes")) { $boolean_answer = true; $good_answer = true; } if (($yn == "n") || ($yn == "no")) { $boolean_answer = false; $good_answer = true; } } while (!$good_answer); return $boolean_answer; } function console_get_interface_from_ppp($realif) { global $config; if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) { foreach ($config['ppps']['ppp'] as $pppid => $ppp) { if ($realif == $ppp['if']) { $ifaces = explode(",", $ppp['ports']); return $ifaces[0]; } } } return ""; } function prompt_for_enable_dhcp_server($version = 4) { global $config, $fp, $interface; if ($interface == "wan") { if ($config['interfaces']['lan']) { return false; } } /* only allow DHCP server to be enabled when static IP is configured on this interface */ if ($version === 6) { $is_ipaddr = is_ipaddrv6($config['interfaces'][$interface]['ipaddrv6']); } else { $is_ipaddr = is_ipaddrv4($config['interfaces'][$interface]['ipaddr']); } if (!($is_ipaddr)) { return false; } $label_DHCP = ($version === 6) ? "DHCP6" : "DHCP"; $upperifname = strtoupper($interface); return console_prompt_for_yn (sprintf(gettext("Do you want to enable the %s server on %s?"), $label_DHCP, $upperifname)); } function get_interface_config_description($iface) { global $config; $c = $config['interfaces'][$iface]; if (!$c) { return null; } $if = $c['if']; $result = $if; $result2 = array(); $ipaddr = $c['ipaddr']; $ipaddrv6 = $c['ipaddrv6']; if (is_ipaddr($ipaddr)) { $result2[] = "static"; } else if ($ipaddr == "dhcp") { $result2[] = "dhcp"; } if (is_ipaddr($ipaddrv6)) { $result2[] = "staticv6"; } else if ($ipaddrv6 == "dhcp6") { $result2[] = "dhcp6"; } if (count($result2)) { $result .= " - " . implode(", ", $result2); } return $result; } $fp = fopen('php://stdin', 'r'); /* build an interface collection */ $ifdescrs = get_configured_interface_with_descr(false, true); $count = count($ifdescrs); /* grab interface that we will operate on, unless there is only one interface */ if ($count > 1) { echo "Available interfaces:\n\n"; $x=1; foreach ($ifdescrs as $iface => $ifdescr) { $config_descr = get_interface_config_description($iface); echo "{$x} - {$ifdescr} ({$config_descr})\n"; $x++; } echo "\nEnter the number of the interface you wish to configure: "; $intnum = chop(fgets($fp)); } else { $intnum = $count; } if ($intnum < 1) { return; } if ($intnum > $count) { return; } $index = 1; foreach ($ifdescrs as $ifname => $ifdesc) { if ($intnum == $index) { $interface = $ifname; break; } else { $index++; } } if (!$interface) { echo "Invalid interface!\n"; return; } $ifaceassigned = ""; function next_unused_gateway_name($interface) { global $g, $config; $new_name = "GW_" . strtoupper($interface); if (!is_array($config['gateways']['gateway_item'])) { return $new_name; } $count = 1; do { $existing = false; foreach ($config['gateways']['gateway_item'] as $item) { if ($item['name'] === $new_name) { $existing = true; break; } } if ($existing) { $count += 1; $new_name = "GW_" . strtoupper($interface) . "_" . $count; } } while ($existing); return $new_name; } function add_gateway_to_config($interface, $gatewayip, $inet_type) { global $g, $config, $dry_run; if (!is_array($config['gateways']['gateway_item'])) { $config['gateways']['gateway_item'] = array(); } $a_gateways = &$config['gateways']['gateway_item']; if ($dry_run) { print_r($a_gateways); } $new_name = ''; $is_default = true; foreach ($a_gateways as $item) { if ($item['ipprotocol'] === $inet_type) { if (isset($item['defaultgw'])) { $is_default = false; } if (($item['interface'] === $interface) && ($item['gateway'] === $gatewayip)) { $new_name = $item['name']; } } } if ($new_name == '') { $new_name = next_unused_gateway_name($interface); $item = array( "interface" => $interface, "gateway" => $gatewayip, "name" => $new_name, "weight" => 1, "ipprotocol" => $inet_type, "interval" => true, "descr" => "Interface $interface Gateway", "defaultgw" => $is_default ); if ($dry_run) { print_r($item); } $a_gateways[] = $item; } return $new_name; } function console_configure_ip_address($version) { global $g, $config, $interface, $restart_dhcpd, $ifaceassigned, $fp; $label_IPvX = ($version === 6) ? "IPv6" : "IPv4"; $maxbits = ($version === 6) ? 127 : 31; $label_DHCP = ($version === 6) ? "DHCP6" : "DHCP"; $upperifname = strtoupper($interface); if ($interface == "wan") { if (console_prompt_for_yn (sprintf(gettext("Configure %s address %s interface via %s?"), $label_IPvX, $upperifname, $label_DHCP))) { $ifppp = console_get_interface_from_ppp(get_real_interface("wan")); if (!empty($ifppp)) { $ifaceassigned = $ifppp; } $intip = ($version === 6) ? "dhcp6" : "dhcp"; $intbits = ""; $isintdhcp = true; $restart_dhcpd = true; } } if ($isintdhcp == false or $interface <> "wan") { while (true) { do { echo "\n" . sprintf(gettext("Enter the new %s %s address. Press for none:"), $upperifname, $label_IPvX) . "\n> "; $intip = chop(fgets($fp)); $is_ipaddr = ($version === 6) ? is_ipaddrv6($intip) : is_ipaddrv4($intip); if ($is_ipaddr && is_ipaddr_configured($intip, $interface, true)) { $ip_conflict = true; echo gettext("This IP address conflicts with another interface or a VIP") . "\n"; } else { $ip_conflict = false; } } while (($ip_conflict === true) || !($is_ipaddr || $intip == '')); if ($intip != '') { echo "\n" . sprintf(gettext("Subnet masks are entered as bit counts (as in CIDR notation) in %s."), $g['product_name']) . "\n"; if ($version === 6) { echo "e.g. ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00 = 120\n"; echo " ffff:ffff:ffff:ffff:ffff:ffff:ffff:0 = 112\n"; echo " ffff:ffff:ffff:ffff:ffff:ffff:0:0 = 96\n"; echo " ffff:ffff:ffff:ffff:ffff:0:0:0 = 80\n"; echo " ffff:ffff:ffff:ffff:0:0:0:0 = 64\n"; } else { echo "e.g. 255.255.255.0 = 24\n"; echo " 255.255.0.0 = 16\n"; echo " 255.0.0.0 = 8\n"; } do { $upperifname = strtoupper($interface); echo "\n" . sprintf(gettext("Enter the new %s %s subnet bit count (1 to %s):"), $upperifname, $label_IPvX, $maxbits) . "\n> "; $intbits = chop(fgets($fp)); $intbits_ok = is_numeric($intbits) && (($intbits >= 1) && ($intbits <= $maxbits)); $restart_dhcpd = true; if ($version === 4 && $intbits < $maxbits) { if ($intip == gen_subnet($intip, $intbits)) { echo gettext("You cannot set network address to an interface"); continue 2; $intbits_ok = false; } else if ($intip == gen_subnet_max($intip, $intbits)) { echo gettext("You cannot set broadcast address to an interface"); continue 2; $intbits_ok = false; } } } while (!$intbits_ok); if ($version === 6) { $subnet = gen_subnetv6($intip, $intbits); } else { $subnet = gen_subnet($intip, $intbits); } do { echo "\n" . sprintf(gettext("For a WAN, enter the new %s %s upstream gateway address."), $upperifname, $label_IPvX) . "\n" . gettext("For a LAN, press for none:") . "\n> "; $gwip = chop(fgets($fp)); $is_ipaddr = ($version === 6) ? is_ipaddrv6($gwip) : is_ipaddrv4($gwip); $is_in_subnet = $is_ipaddr && ip_in_subnet($gwip, $subnet . "/" . $intbits); if ($gwip != '') { if (!$is_ipaddr) { echo sprintf(gettext("not an %s IP address!"), $label_IPvX) . "\n"; } else if (!$is_in_subnet) { echo gettext("not in subnet!") . "\n"; } } } while (!($gwip == '' || ($is_ipaddr && $is_in_subnet))); if ($gwip != '') { $inet_type = ($version === 6) ? "inet6" : "inet"; $gwname = add_gateway_to_config($interface, $gwip, $inet_type); } } $ifppp = console_get_interface_from_ppp(get_real_interface($interface)); if (!empty($ifppp)) { $ifaceassigned = $ifppp; } break; } } return array($intip, $intbits, $gwname); } list($intip, $intbits, $gwname) = console_configure_ip_address(4); list($intip6, $intbits6, $gwname6) = console_configure_ip_address(6); if (!empty($ifaceassigned)) { $config['interfaces'][$interface]['if'] = $ifaceassigned; } $config['interfaces'][$interface]['ipaddr'] = $intip; $config['interfaces'][$interface]['subnet'] = $intbits; $config['interfaces'][$interface]['gateway'] = $gwname; $config['interfaces'][$interface]['ipaddrv6'] = $intip6; $config['interfaces'][$interface]['subnetv6'] = $intbits6; $config['interfaces'][$interface]['gatewayv6'] = $gwname6; $config['interfaces'][$interface]['enable'] = true; function console_configure_dhcpd($version = 4) { global $g, $config, $restart_dhcpd, $fp, $interface, $dry_run, $intip, $intbits, $intip6, $intbits6; $label_IPvX = ($version === 6) ? "IPv6" : "IPv4"; $dhcpd = ($version === 6) ? "dhcpdv6" : "dhcpd"; if ($g['services_dhcp_server_enable'] && prompt_for_enable_dhcp_server($version)) { $subnet_start = ($version === 6) ? gen_subnetv6($intip6, $intbits6) : gen_subnet($intip, $intbits); $subnet_end = ($version === 6) ? gen_subnetv6_max($intip6, $intbits6) : gen_subnet_max($intip, $intbits); do { do { echo sprintf(gettext("Enter the start address of the %s client address range:"), $label_IPvX) . " "; $dhcpstartip = chop(fgets($fp)); if ($dhcpstartip === "") { fclose($fp); return 0; } $is_ipaddr = ($version === 6) ? is_ipaddrv6($dhcpstartip) : is_ipaddrv4($dhcpstartip); $is_inrange = is_inrange($dhcpstartip, $subnet_start, $subnet_end); if (!$is_inrange) { echo gettext("This IP address must be in the interface's subnet") . "\n"; } } while (!$is_ipaddr || !$is_inrange); do { echo sprintf(gettext("Enter the end address of the %s client address range:"), $label_IPvX) . " "; $dhcpendip = chop(fgets($fp)); if ($dhcpendip === "") { fclose($fp); return 0; } $is_ipaddr = ($version === 6) ? is_ipaddrv6($dhcpendip) : is_ipaddrv4($dhcpendip); $is_inrange = is_inrange($dhcpendip, $subnet_start, $subnet_end); if (!$is_inrange) { echo gettext("This IP address must be in the interface's subnet") . "\n"; } $not_inorder = ($version === 6) ? (inet_pton($dhcpendip) < inet_pton($dhcpstartip)) : ip_less_than($dhcpendip, $dhcpstartip); if ($not_inorder) { echo gettext("The end address of the DHCP range must be >= the start address") . "\n"; } } while (!$is_ipaddr || !$is_inrange); } while ($not_inorder); $restart_dhcpd = true; $config[$dhcpd][$interface]['enable'] = true; $config[$dhcpd][$interface]['range']['from'] = $dhcpstartip; $config[$dhcpd][$interface]['range']['to'] = $dhcpendip; } else { if (isset($config[$dhcpd][$interface]['enable'])) { unset($config[$dhcpd][$interface]['enable']); printf(gettext("Disabling %s DHCPD..."), $label_IPvX); $restart_dhcpd = true; } } return 1; } if (console_configure_dhcpd(4) == 0) { return 0; } if (console_configure_dhcpd(6) == 0) { return 0; } //***************************************************************************** if ($config['system']['webgui']['protocol'] == "https") { if (console_prompt_for_yn (gettext("Do you want to revert to HTTP as the webConfigurator protocol?"))) { $config['system']['webgui']['protocol'] = "http"; $restart_webgui = true; } } if (isset($config['system']['webgui']['noantilockout'])) { echo "\n" . sprintf(gettext("Note: the anti-lockout rule on %s has been re-enabled."), $interface) . "\n"; unset($config['system']['webgui']['noantilockout']); } if ($config['interfaces']['lan']) { if ($config['dhcpd']) { if ($config['dhcpd']['wan']) { unset($config['dhcpd']['wan']); } } if ($config['dhcpdv6']) { if ($config['dhcpdv6']['wan']) { unset($config['dhcpdv6']['wan']); } } } if (!$config['interfaces']['lan']) { unset($config['interfaces']['lan']); if ($config['dhcpd']['lan']) { unset($config['dhcpd']['lan']); } if ($config['dhcpdv6']['lan']) { unset($config['dhcpdv6']['lan']); } unset($config['shaper']); unset($config['ezshaper']); unset($config['nat']); if (!$dry_run) { system("rm /var/dhcpd/var/db/* >/dev/null 2>/dev/null"); $restart_dhcpd = true; } } $upperifname = strtoupper($interface); if (!$dry_run) { echo "\nPlease wait while the changes are saved to {$upperifname}..."; write_config(sprintf(gettext("%s IP configuration from console menu"), $interface)); interface_reconfigure(strtolower($upperifname)); echo "\n Reloading filter..."; filter_configure_sync(); echo "\n Reloading routing configuration..."; system_routing_configure(); if ($restart_dhcpd) { echo "\n DHCPD..."; services_dhcpd_configure(); } if ($restart_webgui) { echo "\n Restarting webConfigurator... "; mwexec("/etc/rc.restart_webgui"); } } if ($intip != '') { if (is_ipaddr($intip)) { echo "\n\n" . sprintf(gettext("The IPv4 %s address has been set to %s"), $upperifname, "{$intip}/{$intbits}") . "\n"; } else { echo "\n\n" . sprintf(gettext("The IPv4 %s address has been set to %s"), $upperifname, $intip) . "\n"; } } if ($intip6 != '') { if (is_ipaddr($intip6)) { echo "\n\n" . sprintf(gettext("The IPv6 %s address has been set to %s"), $upperifname, "${intip6}/${intbits6}") . "\n"; } else { echo "\n\n" . sprintf(gettext("The IPv6 %s address has been set to %s"), $upperifname, $intip6) . "\n"; } } if ($intip != '' || $intip6 != '') { if (count($ifdescrs) == "1" or $interface == "lan") { if ($debug) { echo "ifdescrs count is " . count($ifdescrs) . "\n"; echo "interface is {$interface} \n"; } echo gettext('You can now access the webConfigurator by opening the following URL in your web browser:') . "\n"; if (!empty($config['system']['webgui']['port'])) { $webuiport = $config['system']['webgui']['port']; if ($intip != '') { echo " {$config['system']['webgui']['protocol']}://{$intip}:{$webuiport}/\n"; } if ($intip6 != '') { if (is_ipaddr($intip6)) { echo " {$config['system']['webgui']['protocol']}://[{$intip6}]:{$webuiport}/\n"; } else { echo " {$config['system']['webgui']['protocol']}://{$intip6}:{$webuiport}/\n"; } } } else { if ($intip != '') { echo " {$config['system']['webgui']['protocol']}://{$intip}/\n"; } if ($intip6 != '') { if (is_ipaddr($intip6)) { echo " {$config['system']['webgui']['protocol']}://[{$intip6}]/\n"; } else { echo " {$config['system']['webgui']['protocol']}://{$intip6}/\n"; } } } } } echo "\n" . gettext('Press to continue.'); fgets($fp); fclose($fp); ?>