aboutsummaryrefslogtreecommitdiffstats
path: root/config/openbgpd
diff options
context:
space:
mode:
authorjim-p <jimp@pfsense.org>2015-06-05 12:08:44 -0400
committerjim-p <jimp@pfsense.org>2015-06-05 12:08:44 -0400
commit5f8d92438c489cc9ea6d6685e7a541612b10098a (patch)
tree0f8184713f421bb5a4ffa3681551da95ec4ae7fe /config/openbgpd
parente2a343ed332f4220cc5a57536bab98cf86bf4daa (diff)
downloadpfsense-packages-5f8d92438c489cc9ea6d6685e7a541612b10098a.tar.gz
pfsense-packages-5f8d92438c489cc9ea6d6685e7a541612b10098a.tar.bz2
pfsense-packages-5f8d92438c489cc9ea6d6685e7a541612b10098a.zip
Add CARP status support to OpenBGPD so it can be stopped on a secondary unit.
Diffstat (limited to 'config/openbgpd')
-rw-r--r--config/openbgpd/openbgpd.inc116
-rw-r--r--config/openbgpd/openbgpd.xml14
2 files changed, 126 insertions, 4 deletions
diff --git a/config/openbgpd/openbgpd.inc b/config/openbgpd/openbgpd.inc
index c625cff8..038ffa11 100644
--- a/config/openbgpd/openbgpd.inc
+++ b/config/openbgpd/openbgpd.inc
@@ -191,6 +191,46 @@ function openbgpd_install_conf() {
@chmod("{$bgpd_config_base}/bgpd.conf", 0600);
unset($conffile);
+ $carp_ip_status_check = "";
+ if (is_ipaddr($openbgpd_conf['carpstatusip'])) {
+
+ $pfs_version = substr(trim(file_get_contents("/etc/version")),0,3);
+ switch ($pfs_version) {
+ case "2.0":
+ case "2.1":
+ /* Check for 2.1 and before */
+ $carpcheckinterface = trim(find_carp_interface($openbgpd_conf['carpstatusip']));
+ $carp_ip_status_check = <<<EOF
+
+CARP_STATUS=`/sbin/ifconfig {$carpcheckinterface} | /usr/bin/grep carp: | /usr/bin/awk '{print \$2;}'`
+if [ \${CARP_STATUS} != "MASTER" ]; then
+ exit;
+fi
+
+EOF;
+ break;
+ case "2.2":
+ default:
+ /* Check for 2.2 and later */
+ if (is_array($config['virtualip']['vip'])) {
+ foreach ($config['virtualip']['vip'] as $vip) {
+ if (($vip['mode'] == "carp") && ($vip['subnet'] == $openbgpd_conf['carpstatusip'])) {
+ $carpcheckinterface = escapeshellarg(get_real_interface($vip['interface']));
+ $vhid = escapeshellarg($vip['vhid']);
+ $carp_ip_status_check = <<<EOF
+
+CARP_STATUS=`/sbin/ifconfig {$carpcheckinterface} | /usr/bin/grep 'carp:' | /usr/bin/grep 'vhid {$vhid}' | /usr/bin/awk '{print \$2;}'`
+if [ \${CARP_STATUS} != "MASTER" ]; then
+ exit;
+fi
+EOF;
+ }
+ }
+ }
+ break;
+ }
+ }
+
// Create rc.d file
$rc_file_stop = <<<EOF
killall -TERM bgpd
@@ -210,6 +250,7 @@ fi
NUMBGPD=`ps auxw | grep -c '[b]gpd.*parent'`
if [ \${NUMBGPD} -lt 1 ] ; then
+ {$carp_ip_status_check}
{$pkg_bin}/bgpd -f {$bgpd_config_base}/bgpd.conf
else
{$pkg_bin}/bgpctl reload
@@ -225,13 +266,36 @@ EOF;
$_gb = exec("/sbin/sysctl net.inet.ip.ipsec_in_use=1");
// bgpd process running? if so reload, else start.
+
+ // Kick off newly created rc.d script
+ if (is_ipaddr($openbgpd_conf['carpstatusip'])) {
+ $status = openbgpd_get_carp_status_by_ip($openbgpd_conf['carpstatusip']);
+ switch (strtoupper($status)) {
+ // Stop the service if the VIP is in BACKUP or INIT state.
+ case "BACKUP":
+ case "INIT":
+ exec("/usr/local/etc/rc.d/bgpd.sh stop");
+ break;
+ // Start the service if the VIP is MASTER state.
+ case "MASTER":
+ // Assume it's up if the status can't be determined.
+ default:
+ openbgpd_restart();
+ break;
+ }
+ } else {
+ openbgpd_restart();
+ }
+
+ conf_mount_ro();
+}
+
+function openbgpd_restart() {
if(is_openbgpd_running() == true) {
exec("{$pkg_bin}/bgpctl reload");
} else {
exec("{$pkg_bin}/bgpd -f {$bgpd_config_base}/bgpd.conf");
}
-
- conf_mount_ro();
}
// get the raw openbgpd confi file for manual inspection/editing
@@ -362,4 +426,52 @@ function is_openbgpd_running() {
return false;
}
+function openbgpd_get_carp_status_by_ip($ipaddr) {
+ $iface = trim(find_carp_interface($ipaddr));
+ if ($iface) {
+ $status = get_carp_interface_status($iface);
+ // If there is no status for that interface, return null.
+ if (!$status)
+ $status = null;
+ } else {
+ // If there is no VIP by that IP, return null.
+ $status = null;
+ }
+ return $status;
+}
+
+function openbgpd_plugin_carp($pluginparams) {
+ global $config;
+ require_once("service-utils.inc");
+ // Called when a CARP interface changes state
+ // $pluginparams['event'] either 'rc.carpmaster' or 'rc.carpbackup'
+ // $pluginparams['interface'] contains the affected interface
+
+ /* If there is no bgp config, then stop */
+ if(is_array($config['installedpackages']['openbgpd']['config'])) {
+ $openbgpd_conf = &$config['installedpackages']['openbgpd']['config'][0];
+ } else {
+ return null;
+ }
+ /* If there is no properly configured CARP status check IP, then stop */
+ if (!is_ipaddr($openbgpd_conf['carpstatusip'])) {
+ return null;
+ }
+ list($vhid, $iface) = explode("@", trim($pluginparams['interface']));
+ $friendly = convert_real_interface_to_friendly_interface_name($iface);
+ $carp_iface = "{$friendly}_vip${vhid}";
+
+ /* If this CARP transition is not from the IP address to check, then stop. */
+ if (get_interface_ip($carp_iface) != $openbgpd_conf['carpstatusip']) {
+ return null;
+ }
+
+ /* Start or stop the service as needed based on the CARP transition. */
+ if ($pluginparams['event'] == "rc.carpmaster") {
+ start_service("bgpd");
+ } elseif ($pluginparams['event'] == "rc.carpbackup") {
+ stop_service("bgpd");
+ }
+}
+
?>
diff --git a/config/openbgpd/openbgpd.xml b/config/openbgpd/openbgpd.xml
index ff40452a..e7d77786 100644
--- a/config/openbgpd/openbgpd.xml
+++ b/config/openbgpd/openbgpd.xml
@@ -105,6 +105,11 @@
<url>/openbgpd_status.php</url>
</tab>
</tabs>
+ <plugins>
+ <item>
+ <type>plugin_carp</type>
+ </item>
+ </plugins>
<fields>
<field>
<fielddescr>Autonomous Systems (AS) Number</fielddescr>
@@ -143,8 +148,13 @@
<description>Set the router ID to the given IP address, which must be local to the machine.</description>
<type>input</type>
</field>
-
-
+ <field>
+ <fielddescr>CARP Status IP</fielddescr>
+ <fieldname>carpstatusip</fieldname>
+ <description>IP address used to determine the CARP status. When the VIP is in BACKUP status, bgpd will not be started. &lt;br/&gt;NOTE: On 2.1.x and before this requires changes to /etc/rc.carpmaster to start bgpd and /etc/rc.carpbackup to stop bgpd or it will not be fully effective. On pfSense 2.2.x and later, full support is automatic.</description>
+ <type>input</type>
+ <size>25</size>
+ </field>
<field>
<fielddescr>Networks</fielddescr>
<fieldname>network</fieldname>