summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorScott Ullrich <sullrich@pfsense.org>2005-06-21 04:17:15 +0000
committerScott Ullrich <sullrich@pfsense.org>2005-06-21 04:17:15 +0000
commita26686cbb8e4cfa44237b686fdb76c4a3292f5e7 (patch)
tree6e0fd5fa732ee829b990187774b6c5e2e105a64a
parent34a0d36a36b3b6a03200f46c2552e09fe7e30b0b (diff)
downloadpfsense-a26686cbb8e4cfa44237b686fdb76c4a3292f5e7.zip
pfsense-a26686cbb8e4cfa44237b686fdb76c4a3292f5e7.tar.gz
Move carp to base
-rw-r--r--usr/local/pkg/carp.xml237
-rw-r--r--usr/local/pkg/carp_settings.xml122
-rwxr-xr-xusr/local/www/carp_status.php166
-rwxr-xr-xusr/local/www/fbegin.inc1
4 files changed, 526 insertions, 0 deletions
diff --git a/usr/local/pkg/carp.xml b/usr/local/pkg/carp.xml
new file mode 100644
index 0000000..02a78d2
--- /dev/null
+++ b/usr/local/pkg/carp.xml
@@ -0,0 +1,237 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<packagegui>
+ <name>carp</name>
+ <version>0.1.0</version>
+ <xmlver>$Revision$</xmlver>
+ <title>Services: CARP (failover)</title>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>CARP (failover)</name>
+ <tooltiptext>CARP is a tool to help achieve system redundancy, by having multiple computers creating a single, virtual network interface between them.</tooltiptext>
+ <section>Services</section>
+ <url>carp_status.php</url>
+ </menu>
+ <tabs>
+ <tab>
+ <text>CARP Virtual IPs</text>
+ <url>/pkg_edit.php?xml=carp.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>CARP Status</text>
+ <url>carp_status.php</url>
+ </tab>
+ <tab>
+ <text>CARP Settings</text>
+ <url>pkg_edit.php?xml=carp_settings.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>a+rx</chmod>
+ <item>http://www.pfsense.com/packages/config/carp_settings.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/pf/</prefix>
+ <chmod>a+rx</chmod>
+ <item>http://www.pfsense.com/packages/config/carp_sync_client.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>a+rx</chmod>
+ <nosync/>
+ <item>http://www.pfsense.com/packages/config/carp_sync_server.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>a+rx</chmod>
+ <item>http://www.pfsense.com/packages/config/carp_status.php</item>
+ </additional_files_needed>
+ <!-- configpath gets expanded out automatically and config items will be
+ stored in that location -->
+ <configpath>['installedpackages']['carp']['config']</configpath>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>VHID Group</fielddescr>
+ <fieldname>vhid</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Virtual IP Address</fielddescr>
+ <fieldname>ipaddress</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Advertising Frequency</fielddescr>
+ <fieldname>advskew</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Netmask</fielddescr>
+ <fieldname>netmask</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <!-- fields gets invoked when the user adds or edits a item. the following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes. -->
+ <fields>
+ <field>
+ <fielddescr>Virtual IP Address</fielddescr>
+ <fieldname>ipaddress</fieldname>
+ <description>Enter the IP Address that you would like to share on both machines</description>
+ <type>input</type>
+ </field>
+<!--
+ <field>
+ <fielddescr>Bind Virtual IP to interface</fielddescr>
+ <fieldname>interface</fieldname>
+ <description>Select the interface that this IP should bind to (carpdev). Leave this set to AUTO for the system to automatically deterimine where to setup the IP.</description>
+ <add_to_interfaces_selection>AUTO</add_to_interfaces_selection>
+ <size>3</size>
+ <value>AUTO</value>
+ <type>interfaces_selection</type>
+ </field>
+-->
+ <field>
+ <fielddescr>Virtual IP Netmask</fielddescr>
+ <fieldname>netmask</fieldname>
+ <description>Enter the IP Address's netmask that you would like to share on both machines</description>
+ <type>select</type>
+ <value>24</value>
+ <options>
+ <option><value>1</value><name>1</name></option>
+ <option><value>2</value><name>2</name></option>
+ <option><value>3</value><name>3</name></option>
+ <option><value>4</value><name>4</name></option>
+ <option><value>5</value><name>5</name></option>
+ <option><value>6</value><name>6</name></option>
+ <option><value>7</value><name>7</name></option>
+ <option><value>8</value><name>8</name></option>
+ <option><value>9</value><name>9</name></option>
+ <option><value>10</value><name>10</name></option>
+ <option><value>11</value><name>11</name></option>
+ <option><value>12</value><name>12</name></option>
+ <option><value>13</value><name>13</name></option>
+ <option><value>14</value><name>14</name></option>
+ <option><value>15</value><name>15</name></option>
+ <option><value>16</value><name>16</name></option>
+ <option><value>17</value><name>17</name></option>
+ <option><value>18</value><name>18</name></option>
+ <option><value>19</value><name>19</name></option>
+ <option><value>20</value><name>20</name></option>
+ <option><value>21</value><name>21</name></option>
+ <option><value>22</value><name>22</name></option>
+ <option><value>23</value><name>23</name></option>
+ <option><value>24</value><name>24</name></option>
+ <option><value>25</value><name>25</name></option>
+ <option><value>26</value><name>26</name></option>
+ <option><value>27</value><name>27</name></option>
+ <option><value>28</value><name>28</name></option>
+ <option><value>29</value><name>29</name></option>
+ <option><value>30</value><name>30</name></option>
+ <option><value>31</value><name>31</name></option>
+ <option><value>32</value><name>32</name></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Virtual IP Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>Enter the VHID group password.</description>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>VHID Group</fielddescr>
+ <fieldname>vhid</fieldname>
+ <description>Enter the VHID group that the machines will share</description>
+ <type>select</type>
+ <value>1</value>
+ <options>
+ <option><value>1</value><name>1 (DEFAULT)</name></option>
+ <option><value>2</value><name>2</name></option>
+ <option><value>3</value><name>3</name></option>
+ <option><value>4</value><name>4</name></option>
+ <option><value>5</value><name>5</name></option>
+ <option><value>6</value><name>6</name></option>
+ <option><value>7</value><name>7</name></option>
+ <option><value>8</value><name>8</name></option>
+ <option><value>9</value><name>9</name></option>
+ <option><value>10</value><name>10</name></option>
+ <option><value>11</value><name>11</name></option>
+ <option><value>12</value><name>12</name></option>
+ <option><value>13</value><name>13</name></option>
+ <option><value>14</value><name>14</name></option>
+ <option><value>15</value><name>15</name></option>
+ <option><value>16</value><name>16</name></option>
+ <option><value>17</value><name>17</name></option>
+ <option><value>18</value><name>18</name></option>
+ <option><value>19</value><name>19</name></option>
+ <option><value>20</value><name>20</name></option>
+ <option><value>21</value><name>21</name></option>
+ <option><value>22</value><name>22</name></option>
+ <option><value>23</value><name>23</name></option>
+ <option><value>24</value><name>24</name></option>
+ <option><value>25</value><name>25</name></option>
+ <option><value>26</value><name>26</name></option>
+ <option><value>27</value><name>27</name></option>
+ <option><value>28</value><name>28</name></option>
+ <option><value>29</value><name>29</name></option>
+ <option><value>30</value><name>30</name></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Advertising Frequency</fielddescr>
+ <fieldname>advskew</fieldname>
+ <description>The frequency that this machine will advertise. 0 = master. Anything above 0 designates a backup.</description>
+ <type>select</type>
+ <value>0</value>
+ <options>
+ <option><value>0</value><name>0 (DEFAULT)</name></option>
+ <option><value>1</value><name>1</name></option>
+ <option><value>2</value><name>2</name></option>
+ <option><value>3</value><name>3</name></option>
+ <option><value>4</value><name>4</name></option>
+ <option><value>5</value><name>5</name></option>
+ <option><value>6</value><name>6</name></option>
+ <option><value>7</value><name>7</name></option>
+ <option><value>8</value><name>8</name></option>
+ <option><value>9</value><name>9</name></option>
+ <option><value>10</value><name>10</name></option>
+ <option><value>11</value><name>11</name></option>
+ <option><value>12</value><name>12</name></option>
+ <option><value>13</value><name>13</name></option>
+ <option><value>14</value><name>14</name></option>
+ <option><value>15</value><name>15</name></option>
+ <option><value>16</value><name>16</name></option>
+ <option><value>17</value><name>17</name></option>
+ <option><value>18</value><name>18</name></option>
+ <option><value>19</value><name>19</name></option>
+ <option><value>20</value><name>20</name></option>
+ <option><value>21</value><name>21</name></option>
+ <option><value>22</value><name>22</name></option>
+ <option><value>23</value><name>23</name></option>
+ <option><value>24</value><name>24</name></option>
+ <option><value>25</value><name>25</name></option>
+ <option><value>26</value><name>26</name></option>
+ <option><value>27</value><name>27</name></option>
+ <option><value>28</value><name>28</name></option>
+ <option><value>29</value><name>29</name></option>
+ <option><value>30</value><name>30</name></option>
+ </options>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ </custom_php_command_before_form>
+ <custom_add_php_command_late>
+ interfaces_carp_configure();
+ interfaces_carp_bringup();
+ </custom_add_php_command_late>
+ <custom_php_resync_config_command>
+ </custom_php_resync_config_command>
+ <custom_delete_php_command>
+ interfaces_carp_configure();
+ interfaces_carp_bringup();
+ </custom_delete_php_command>
+ <custom_php_deinstall_command>
+ unlink_if_exists("/usr/local/www/carp*");
+ unlink_if_exists("/usr/local/pkg/carp*");
+ unlink_if_exists("/usr/local/pkg/pf/carp*");
+ unlink_if_exists("/usr/local/etc/rc.d/carp*");
+ unlink_if_exists("/usr/local/pkg/pf/carp*");
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/usr/local/pkg/carp_settings.xml b/usr/local/pkg/carp_settings.xml
new file mode 100644
index 0000000..3c1c215
--- /dev/null
+++ b/usr/local/pkg/carp_settings.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<packagegui>
+ <name>carpsettings</name>
+ <version>0.1.0</version>
+ <title>Services: CARP Settings</title>
+ <!-- configpath gets expanded out automatically and config items will be
+ stored in that location -->
+ <configpath>['installedpackages']['carpsettings']['config']</configpath>
+ <aftersaveredirect>pkg_edit.php?xml=carp_settings.xml&amp;id=0</aftersaveredirect>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>CARP (failover)</name>
+ <tooltiptext>CARP is a tool to help achieve system redundancy, by having multiple computers creating a single, virtual network interface between them, so that if any machine fails, another can respond instead, and/or allowing a degree of load sharing between systems. CARP is an improvement over the Virtual Router Redundancy Protocol (VRRP) standard. It was developed after VRRP was deemed to be not free enough because of a possibly-overlapping Cisco patent.</tooltiptext>
+ <section>Services</section>
+ <configfile>carp.xml</configfile>
+ </menu>
+ <tabs>
+ <tab>
+ <text>CARP Virtual IPs</text>
+ <url>/pkg.php?xml=carp.xml</url>
+ </tab>
+ <tab>
+ <text>CARP Status</text>
+ <url>carp_status.php</url>
+ </tab>
+ <tab>
+ <text>CARP Settings</text>
+ <url>pkg_edit.php?xml=carp_settings.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ </tabs>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>PFSync Enabled</fielddescr>
+ <fieldname>pfsyncenabled</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>PFSync IP</fielddescr>
+ <fieldname>pfsyncip</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>PFSync Interface</fielddescr>
+ <fieldname>pfsyncinterface</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Load Balancing</fielddescr>
+ <fieldname>balancing</fieldname>
+ <type>checkbox</type>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Preemption</fielddescr>
+ <fieldname>premption</fieldname>
+ <type>checkbox</type>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <!-- fields gets invoked when the user adds or edits a item. the following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes. -->
+ <fields>
+ <field>
+ <fielddescr>Synchronize Enabled</fielddescr>
+ <fieldname>pfsyncenabled</fieldname>
+ <description>PFSync transfers state insertion, update, and deletion messages between firewalls. Each firewall sends these messages out via multicast on a specified interface, using the PFSYNC protocol (IP Protocol 240). It also listens on that interface for similar messages from other firewalls, and imports them into the local state table.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Synchronize Interface</fielddescr>
+ <fieldname>pfsyncinterface</fieldname>
+ <type>interfaces_selection</type>
+ <description>If Synchronize State is enabled, it will utilize this interface for communication. NOTE! You must define a IP on each machine participating in this failover group. NOTE: You must have an IP assigned to the interface on any participating sync nodes.</description>
+ </field>
+ <field>
+ <fielddescr>Load Balancing</fielddescr>
+ <fieldname>balancing</fieldname>
+ <description>If this feature is enabled, CARP source-hashes the originating IP of a request. The hash is then used to select a virtual host from the available pool to handle the request. This is disabled by default.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Preemption</fielddescr>
+ <fieldname>premption</fieldname>
+ <description>When preemption is enabled, each CARP host will look at the advskew (Advertising Frequency) parameter in the advertisements it receives from the master, to try to determine whether it can advertise more frequently. If so, it will begin advertising, and the current master, seeing that there is another host with a lower advskew, will bow out.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Synchronize rules</fielddescr>
+ <fieldname>synchronizerules</fieldname>
+ <description>When this option is enabled, this system will automatically sync the firewalls rules over to the other carp when changes are made..</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Synchronize aliases</fielddescr>
+ <fieldname>synchronizealiases</fieldname>
+ <description>When this option is enabled, this system will automatically sync the aliases over to the other carp when changes are made.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Synchronize nat</fielddescr>
+ <fieldname>synchronizenat</fieldname>
+ <description>When this option is enabled, this system will automatically sync the nat rules over to the other carp host when changes are made.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Synchronize traffic shaper</fielddescr>
+ <fieldname>synchronizetrafficshaper</fieldname>
+ <description>When this option is enabled, this system will automatically sync the traffic shaper rules over to the other carp host when changes are made.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Synchronize to IP</fielddescr>
+ <fieldname>synchronizetoip</fieldname>
+ <description>Enter the IP address of the firewall you would like to synchronize your rules to.</description>
+ <type>input</type>
+ <note>Note: CARP sync is currently only supported over http connections - make sure the remote system's
+ WebGUI protocol is set to this!</note>
+ </field>
+ <field>
+ <fielddescr>Remote System Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>Enter the webGUI password of the system that you would like to synchronize with.</description>
+ <type>password</type>
+ </field>
+ </fields>
+</packagegui>
diff --git a/usr/local/www/carp_status.php b/usr/local/www/carp_status.php
new file mode 100755
index 0000000..1de0a2d
--- /dev/null
+++ b/usr/local/www/carp_status.php
@@ -0,0 +1,166 @@
+#!/usr/local/bin/php
+<?php
+/*
+ carp_status.php
+ Copyright (C) 2004 Scott Ullrich
+ 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.
+*/
+
+require("guiconfig.inc");
+require("xmlparse_pkg.inc");
+
+function gentitle_pkg($pgname) {
+ global $config;
+ return $config['system']['hostname'] . "." . $config['system']['domain'] . " - " . $pgname;
+}
+
+$status = get_carp_status();
+if($_POST['disablecarp'] <> "") {
+ if($status == true) {
+ $carp_counter=find_number_of_created_carp_interfaces();
+ mwexec("/sbin/sysctl net.inet.carp.allow=0");
+ for($x=0; $x<$carp_counter; $x++) {
+ mwexec("/sbin/ifconfig carp{$x} down");
+ mwexec("/sbin/ifconfig carp{$x} destroy");
+ }
+ $savemsg = "{$carp_counter} IPs have been disabled.";
+ } else {
+ $savemsg = "CARP has been enabled.";
+ mwexec("/sbin/sysctl net.inet.carp.allow=1");
+ interfaces_carp_configure();
+ interfaces_carp_bringup();
+ }
+}
+
+$status = get_carp_status();
+?>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<?php $title = "CARP: Status"; ?>
+<title><?=gentitle_pkg($title);?></title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<link href="gui.css" rel="stylesheet" type="text/css">
+</head>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php
+include("fbegin.inc");
+?>
+<p class="pgtitle"><?=$title?></p>
+<form action="carp_status.php" method="post">
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td>
+ <ul id="tabnav">
+ <li class="tabinact"><a href="/pkg.php?xml=carp.xml">CARP Virtual IPs</a></li>
+ <li class="tabact">CARP Status</li>
+ <li class="tabinact"><a href="/pkg_edit.php?xml=carp_settings.xml&id=0">CARP Settings</a></li>
+ </ul>
+</td></tr>
+<tr><td class="tabcont">
+
+<?php
+ if($status == false) {
+ $carp_enabled = false;
+ echo "<input type=\"submit\" name=\"disablecarp\" id=\"disablecarp\" value=\"Enable Carp\">";
+ } else {
+ $carp_enabled = true;
+ echo "<input type=\"submit\" name=\"disablecarp\" id=\"disablecarp\" value=\"Disable Carp\">";
+ }
+
+if(!is_array($config['installedpackages']['carp']['config'])) {
+ echo "</td></tr></table>Could not locate any defined CARP interfaces.";
+ exit;
+}
+?>
+
+<p>
+
+<table width="100%" border="0" cellpadding="6" cellspacing="0">
+</tr>
+<tr>
+ <td class="listhdrr"><b><center>Carp Interface</center></b></td>
+ <td class="listhdrr"><b><center>Virtual IP</center></b></td>
+ <td class="listhdrr"><b><center>Status</center></b></td>
+</tr>
+<?php
+
+if($config['installedpackages']['carp']['config'] <> "")
+ $carpint=0;
+ foreach($config['installedpackages']['carp']['config'] as $carp) {
+ $ipaddress = $carp['ipaddress'];
+ $premption = $carp['premption'];
+ $password = $carp['password'];
+ $netmask = $carp['netmask'];
+ $vhid = $carp['vhid'];
+ $advskew = $carp['advskew'];
+ $pfsync = $carp['pfsync'];
+ $synciface = $carp['synciface'];
+ $carp_int = find_carp_interface($ipaddress);
+ $status = get_carp_interface_status($carp_int);
+ if(isset($carp['balancing'])) $balancing = "true"; else $balancing = "false";
+ if(isset($carp['premption'])) $premption = "true"; else $premption = "false";
+ echo "<tr>";
+ $align = "valign='middle'";
+ if($carp_enabled == false) {
+ $icon = "<img {$align} src='/block.gif'>";
+ $status = "DISABLED";
+ $carp_int = "carp" . $carpint;
+ } else {
+ if($status == "MASTER") {
+ $icon = "<img {$align} src='/pass.gif'>";
+ } else if($status == "BACKUP") {
+ $icon = "<img {$align} src='/pass_d.gif'>";
+ } else if($status == "INIT") {
+ $icon = "<img {$align} src='/log.gif'>";
+ }
+ }
+ echo "<td class=\"listlr\"><center>" . $carp_int . "&nbsp;</td>";
+ echo "<td class=\"listlr\"><center>" . $ipaddress . "&nbsp;</td>";
+ echo "<td class=\"listlr\"><center>{$icon}&nbsp;&nbsp;" . $status . "&nbsp;</td>";
+ echo "</tr>";
+ $carpint++;
+ }
+
+?>
+<tr><td>
+<center>
+<?php
+ echo "<br>pfSync nodes:<br>";
+ echo "<pre>";
+ system("/sbin/pfctl -vvss | /usr/bin/grep creator | /usr/bin/cut -d\" \" -f7 | /usr/bin/sort -u");
+ echo "</pre>";
+?>
+</center>
+</td></tr>
+</table>
+</td></tr>
+</table>
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
+
diff --git a/usr/local/www/fbegin.inc b/usr/local/www/fbegin.inc
index d857684..3e519e5 100755
--- a/usr/local/www/fbegin.inc
+++ b/usr/local/www/fbegin.inc
@@ -98,6 +98,7 @@ function showhide(tspan, tri) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="/services_snmp.php" class="navlnk">SNMP</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="/services_proxyarp.php" class="navlnk">Proxy ARP</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="/services_wol.php" class="navlnk">Wake on LAN</a><br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="/carp_status.php" class="navlnk">CARP (failover)/a><br>
<?php echo return_ext_menu("Services"); ?>
<strong>VPN</strong><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="/vpn_ipsec.php" class="navlnk">IPsec</a><br>
OpenPOWER on IntegriCloud