From 8488b5a6e0f662a8e4405fd5f1209792440a400e Mon Sep 17 00:00:00 2001 From: jim-p Date: Thu, 8 Mar 2012 16:30:06 -0500 Subject: First attempt at a Quagga-OSPF package to make OpenOSPFd obsolete. If anyone wants to build on this to support all of quagga's routing protocols, have at it. --- config/quagga_ospfd/quagga_ospfd.inc | 270 ++++++++++++++++++++++++ config/quagga_ospfd/quagga_ospfd.xml | 173 +++++++++++++++ config/quagga_ospfd/quagga_ospfd_interfaces.xml | 128 +++++++++++ config/quagga_ospfd/quaggactl | 75 +++++++ config/quagga_ospfd/status_ospfd.php | 129 +++++++++++ 5 files changed, 775 insertions(+) create mode 100644 config/quagga_ospfd/quagga_ospfd.inc create mode 100644 config/quagga_ospfd/quagga_ospfd.xml create mode 100644 config/quagga_ospfd/quagga_ospfd_interfaces.xml create mode 100644 config/quagga_ospfd/quaggactl create mode 100644 config/quagga_ospfd/status_ospfd.php (limited to 'config/quagga_ospfd') diff --git a/config/quagga_ospfd/quagga_ospfd.inc b/config/quagga_ospfd/quagga_ospfd.inc new file mode 100644 index 00000000..2a068022 --- /dev/null +++ b/config/quagga_ospfd/quagga_ospfd.inc @@ -0,0 +1,270 @@ + $ifacename) { + $tmp["name"] = $ifacename; + $tmp["value"] = $iface; + $ospf_ifs[] = $tmp; + } + + foreach (array('server', 'client') as $mode) { + if (is_array($config['openvpn']["openvpn-{$mode}"])) { + foreach ($config['openvpn']["openvpn-{$mode}"] as $id => $setting) { + if (!isset($setting['disable'])) { + $tmp["name"] = gettext("OpenVPN") . " ".$mode.": ".htmlspecialchars($setting['description']); + $tmp["value"] = 'ovpn' . substr($mode, 0, 1) . $setting['vpnid']; + $ospf_ifs[] = $tmp; + } + } + } + } + + return $ospf_ifs; +} + +function quagga_ospfd_install_conf() { + global $config, $g, $input_errors; + + conf_mount_rw(); + + if ($config['installedpackages']['quaggaospfd']['rawconfig'] && $config['installedpackages']['quaggaospfd']['rawconfig']['item']) { + // if there is a raw config specifyed in tthe config.xml use that instead of the assisted config + $conffile = implode("\n",$config['installedpackages']['quaggaospfd']['rawconfig']['item']); + //$conffile = $config['installedpackages']['quaggaospfd']['rawconfig']; + } else { + // generate ospfd.conf based on the assistant + if($config['installedpackages']['quaggaospfd']['config']) + $ospfd_conf = &$config['installedpackages']['quaggaospfd']['config'][0]; + else { + log_error("Quagga OSPFd: No config data found."); + return; + } + + $conffile = "# This file was created by the pfSense package manager. Do not edit!\n\n"; + + if($ospfd_conf['password']) + $conffile .= "password {$ospfd_conf['password']}\n"; + + if ($ospfd_conf['logging']) + $conffile .= "log syslog\n"; + + /* Interface Settings */ + $passive_interfaces = array(); + $interface_networks = array(); + if ($config['installedpackages']['quaggaospfdinterfaces']['config']) { + foreach ($config['installedpackages']['quaggaospfdinterfaces']['config'] as $conf) { + $realif = get_real_interface($conf['interface']); + $conffile .= "interface {$realif}\n" ; + if (!empty($conf['metric'])) { + $conffile .= " ip ospf cost {$conf['metric']}\n"; + } + if (!empty($conf['hellointervalinseconds'])) { + $conffile .= " ip ospf hello-interval {$conf['hellointervalinseconds']}\n"; + } + if ($conf['md5password'] && !empty($conf['password'])) { + $conffile .= " ip ospf authentication message-digest\n"; + $conffile .= " ip ospf message-digest-key 1 md5 \"" . substr($conf['password'], 0, 15) . "\"\n"; + } else if (!empty($conf['password'])) { + $conffile .= " ip ospf authentication-key \"" . substr($conf['password'], 0, 8) . "\"\n"; + } + if (!empty($conf['routerpriorityelections'])) { + $conffile .= " ip ospf priority {$conf['routerpriorityelections']}\n"; + } + if (!empty($conf['retransmitinterval'])) { + $conffile .= " ip ospf retransmit-interval {$conf['retransmitinterval']}\n"; + } + if (!empty($conf['deadtimer'])) { + $conffile .= " ip ospf dead-interval {$conf['deadtimer']}\n"; + } + if (!empty($conf['passive'])) { + $passive_interfaces[] = $realif; + } + $interface_ip = find_interface_ip($realif); + $interface_subnet = find_interface_subnet($realif); + /* Cheap hack since point-to-points won't attach if /32 is used. */ + if ($interface_subnet == 32) + $interface_subnet = 30; + $subnet = gen_subnet($interface_ip, $interface_subnet); + $interface_networks[] = "{$subnet}/{$interface_subnet}"; + } + } + + /* OSPF Settings */ + + $conffile .= "\n\nrouter ospf\n"; + + // Specify router id + if($ospfd_conf['routerid']) + $conffile .= " ospf router-id {$ospfd_conf['routerid']}\n"; + + if ($ospfd_conf['updatefib']) + $conffile .= " area {$ospfd_conf['area']} stub\n"; + + if ($ospfd_conf['logging'] && $ospfd_conf['adjacencylog']) + $conffile .= " log-adjacency-changes detail\n"; + + if ($ospfd_conf['redistributeconnectedsubnets']) + $conffile .= " redistribute connected\n"; + + if ($ospfd_conf['redistributestatic']) + $conffile .= " redistribute static\n"; + + if ($ospfd_conf['redistributedefaultroute']) + $conffile .= " default-information originate\n"; + + if ($ospfd_conf['spfholdtime'] || $ospfd_conf['spfdelay']) { + $spf_minhold = ($ospfd_conf['spfholdtime']) ? $ospfd_conf['spfholdtime'] : 1000; + $spf_maxhold = $spf_minhold * 10; + $spf_delay = ($ospfd_conf['spfdelay']) ? $ospfd_conf['spfdelay'] : 200; + $conffile .= " timers throttle spf {$spf_delay} {$spf_minhold} {$spf_maxhold}\n"; + } + + if ($ospfd_conf['rfc1583']) + $conffile .= " ospf rfc1583compatibility\n"; + + if (is_array($passive_interfaces)) + foreach ($passive_interfaces as $pint) + $conffile .= " passive-interface {$pint}\n"; + + if (is_array($interface_networks)) + foreach ($interface_networks as $ifn) + $conffile .= " network {$ifn} area {$ospfd_conf['area']}\n"; + + if (is_array($ospfd_conf['row'])) { + foreach ($ospfd_conf['row'] as $redistr) { + if (isset($redistr['redistribute'])) + $conffile .= " no "; + $conffile .= " network {$redistr['routevalue']} area {$ospfd_conf['area']}\n"; + } + } + } + + $fd = fopen("/usr/local/etc/quagga/ospfd.conf", "w"); + + // Write out the configuration file + fwrite($fd, $conffile); + + // Close file handle + fclose($fd); + + /* Make zebra config */ + $zebraconffile = "# This file was created by the pfSense package manager. Do not edit!\n\n"; + if($ospfd_conf['password']) + $zebraconffile .= "password {$ospfd_conf['password']}\n"; + if ($ospfd_conf['logging']) + $zebraconffile .= "log syslog\n"; + $fd = fopen("/usr/local/etc/quagga/zebra.conf", "w"); + fwrite($fd, $zebraconffile); + fclose($fd); + + // Create rc.d file + $rc_file_stop = << "quagga.sh", + "start" => $rc_file_start, + "stop" => $rc_file_stop + ) + ); + + // Ensure files have correct permissions + exec("chmod a+rx /usr/local/etc/rc.d/quagga.sh"); + exec("chmod u+rw,go-rw /usr/local/etc/quagga/ospfd.conf"); + exec("chmod u+rw,go-rw /usr/local/etc/quagga/zebra.conf"); + + // Kick off newly created rc.d script + exec("/usr/local/etc/rc.d/quagga.sh restart"); + + // Back to RO mount for NanoBSD and friends + conf_mount_ro(); +} + +function quagga_ospfd_validate_interface() { + global $config, $g, $id, $input_errors; + + if ($config['installedpackages']['quaggaospfdinterfaces']['config']) { + foreach ($config['installedpackages']['quaggaospfdinterfaces']['config'] as $index => $conf) { + if ($index == 0) + continue; + if ($id != $index && $conf['interface'] == $_POST['interface']) + $input_errors[] = "Interface {$_POST['interface']} is already configured."; + } + } + if ($_POST['md5password'] && empty($_POST['password'])) + $input_errors[] = "Please input a password."; +} + +function quagga_ospfd_validate_input() { + global $config, $g, $input_errors; + + if (!empty($_POST['routerid']) && !is_ipaddr($_POST['routerid'])) + $input_errors[] = "Router ID must be an address."; + if (!is_ipaddr($_POST['area'])) + $input_errors[] = "Area needs to be a valid ip_address."; + if ($_POST['spfholdtime'] <> "" && ($_POST['spfholdtime'] < 1 || $_POST['spfholdtime'] > 5)) + $input_errors[] = "SPF holdtime needs to be between 1 and 5."; + if ($_POST['spfdelay'] <> "" && ($_POST['spfdelay'] < 1 || $_POST['spfdelay'] > 10)) + $input_errors[] = "SPF delay needs to be between 1 and 10."; + if (!$config['installedpackages']['quaggaospfdinterfaces']['config']) + $input_errors[] = "Please select an interface to use for Quagga OSPFd."; +} + +// get the raw ospfd confi file for manual inspection/editing +function quagga_ospfd_get_raw_config() { + return file_get_contents("/usr/local/etc/quagga/ospfd.conf"); +} + +// serialize the raw ospfd confi file to config.xml +function quagga_ospfd_put_raw_config($conffile) { + global $config; + if ($conffile == "") + unset($config['installedpackages']['quaggaospfd']['rawconfig']); + else { + $config['installedpackages']['quaggaospfd']['rawconfig'] = array(); + $config['installedpackages']['quaggaospfd']['rawconfig']['item'] = explode("\n",$_POST['quagga_ospfd_raw']); + $config['installedpackages']['quaggaospfd']['rawconfig'] = $conffile; + } +} + +?> diff --git a/config/quagga_ospfd/quagga_ospfd.xml b/config/quagga_ospfd/quagga_ospfd.xml new file mode 100644 index 00000000..3e76c4e4 --- /dev/null +++ b/config/quagga_ospfd/quagga_ospfd.xml @@ -0,0 +1,173 @@ + + quagga_ospfd + 0.1 + Services: Quagga OSPFd + /usr/local/pkg/quagga_ospfd.inc + pkg_edit.php?xml=quagga_ospfd.xml&id=0 + + /usr/local/pkg/ + 644 + http://www.pfsense.com/packages/config/quagga_ospfd/quagga_ospfd.inc + + + /usr/local/pkg/ + 644 + http://www.pfsense.com/packages/config/quagga_ospfd/quagga_ospfd_interfaces.xml + + + /usr/local/www/ + 644 + http://www.pfsense.com/packages/config/quagga_ospfd/status_ospfd.php + + + /usr/local/bin/ + 777 + http://www.pfsense.com/packages/config/quagga_ospfd/quaggactl + + + Quagga OSPFd + Modify Quagga ospfd settings. +
Services
+ quagga_ospfd.xml + /pkg_edit.php?xml=quagga_ospfd.xml&id=0 +
+ + + Global Settings + pkg_edit.php?xml=quagga_ospfd.xml&id=0 + + + + Interface Settings + pkg.php?xml=quagga_ospfd_interfaces.xml + + + Status + /status_ospfd.php + + + + Quagga OSPFd + quagga.sh + ospfd + + + Quagga Zebra + quagga.sh + zebra + + + + Master Password + password + + + + input + + + + Logging + logging + If set to yes, Logs will be written via syslog. + checkbox + + + Log Adjacency Changes + adjacencylog + If set to yes, adjacency changes will be written via syslog. + checkbox + + + Router ID + routerid + + wikipedia. + ]]> + + input + + + Area + area + + wikipedia. + ]]> + + input + + + + Disable FIB updates (Routing table) + updatefib + Disables the updating of the host routing table(turns into stub router). + checkbox + + + Redistribute connected subnets + redistributeconnectedsubnets + Enables the redistribution of connected networks (Default no) + checkbox + + + Redistribute default route + redistributedefaultroute + Enables the redistribution of a default route to this device (Default no) + checkbox + + + Redistribute static + redistributestatic + Enables the redistribution of static routes + checkbox + + + SPF Hold Time + spfholdtime + Set the SPF holdtime in MILLIseconds. The minimum time between two consecutive shortest path first calculations. The default value is 5 seconds; the valid range is 1-5 seconds. + input + + + SPF Delay + spfdelay + Set SPF delay in MILLIseconds. The delay between receiving an update to the link state database and starting the shortest path first calculation. The default value is 1; valid range is 1-10 seconds. + input + + + RFC 1583 compatible + rfc1583 + If set to yes, decisions regarding AS-external routes are evaluated according to RFC 1583. The default is no. + checkbox + + + These rules take precedence over any redistribute options specified above. + none + rowhelper + + + Disable <br/>Redistribution + redistribute + Redistribute rules. + checkbox + 20 + + + Subnet to Route + routevalue + input + 25 + + + + + + quagga_ospfd_install_conf(); + + + quagga_ospfd_validate_input(); + +
\ No newline at end of file diff --git a/config/quagga_ospfd/quagga_ospfd_interfaces.xml b/config/quagga_ospfd/quagga_ospfd_interfaces.xml new file mode 100644 index 00000000..e0f55a58 --- /dev/null +++ b/config/quagga_ospfd/quagga_ospfd_interfaces.xml @@ -0,0 +1,128 @@ + + quagga_ospfd_interfaces + 0.1 + Services: Quagga OSPFd + /usr/local/pkg/quagga_ospfd.inc + pkg.php?xml=quagga_ospfd_interfaces.xml + + /usr/local/pkg/ + 077 + http://www.pfsense.com/packages/config/quagga_ospfd/quagga_ospfd.inc + + + OSPF + Modify Quagga ospfd Interface settings. +
Services
+ quagga_ospfd.xml + /pkg_edit.php?xml=quagga_ospfd.xml&id=0 +
+ + + Global Settings + pkg_edit.php?xml=quagga_ospfd.xml&id=0 + + + Interface Settings + pkg.php?xml=quagga_ospfd_interfaces.xml + + + + Status + /status_ospfd.php + + + + + Interface + interface + + + Description + descr + + + + Quagga OSPFd + quagga.sh + ospfd + + + Quagga Zebra + quagga.sh + zebra + + + + Interface + interface + Enter the desired participating interface here. + select_source + + name + value + + + + Metric + metric + Metric (cost) for this OSPF interface (leave blank for default). + input + + + Description + descr + 30 + input + + + Interface is Passive + passive + Prevent transmission and reception of OSPF packets on this interface. The specified interface will be announced as a stub network. + checkbox + + + Enable MD5 password for this Quagga OSPFd interface (default no) + md5password + Enables the use of an MD5 password to on this instance + checkbox + + + Password + password + Password for this OSPF interface. + input + + + Router Priority + routerpriorityelections + + Router priority when participating in elections for DR (Default 1) Valid range is 0-255. 0 will cause the router to not participate in election. + + input + + + Hello Interval + hellointervalinseconds + Hello Interval this OSPF interface in seconds (Default 10). + input + + + Retransmit Interval + retransmitinterval + Retransmit Interval this OSPF interface in seconds (Default 5). + input + + + Dead Timer + deadtimer + Dead Timer for this OSPF interface in seconds (Default 40). + input + + + + quagga_ospfd_install_conf(); + + + quagga_ospfd_validate_interface(); + +
diff --git a/config/quagga_ospfd/quaggactl b/config/quagga_ospfd/quaggactl new file mode 100644 index 00000000..198a8411 --- /dev/null +++ b/config/quagga_ospfd/quaggactl @@ -0,0 +1,75 @@ +#!/bin/sh +RC_SCRIPT=/usr/local/etc/rc.d/quagga.sh + +ZEBRA_CONFIG=/usr/local/etc/quagga/zebra.conf +ZEBRA_PORT=2601 +ZEBRA_PASSWORD=`/usr/bin/grep '^password ' ${ZEBRA_CONFIG} | /usr/bin/awk '{print $2};'` + +OSPF_CONFIG=/usr/local/etc/quagga/ospfd.conf +OSPF_PORT=2604 +OSPF_PASSWORD=`/usr/bin/grep '^password ' ${OSPF_CONFIG} | /usr/bin/awk '{print $2};'` + +daemon_command() { + COMMANDS=${2} + COMMANDS=${COMMANDS}`echo -e "\n${3}\n"` + COMMANDS=${COMMANDS}`echo -e "\nexit\n"` + echo "$COMMANDS" | /usr/bin/nc localhost ${1} | /usr/bin/tail -n +10 | sed '$d' +} + +case $1 in +stop) + $RC_SCRIPT stop + ;; +start) + $RC_SCRIPT start + ;; +restart) + $RC_SCRIPT restart + ;; +zebra) + case $2 in + cpu*) + daemon_command ${ZEBRA_PORT} ${ZEBRA_PASSWORD} "show thread cpu" + ;; + mem*) + shift; shift; + daemon_command ${ZEBRA_PORT} ${ZEBRA_PASSWORD} "show memory $*" + ;; + int*) + daemon_command ${ZEBRA_PORT} ${ZEBRA_PASSWORD} "show interface $3" + ;; + rou*) + daemon_command ${ZEBRA_PORT} ${ZEBRA_PASSWORD} "show ip route" + ;; + esac ;; +ospf) + case $2 in + cpu*) + daemon_command ${OSPF_PORT} ${OSPF_PASSWORD} "show thread cpu" + ;; + mem*) + shift; shift; + daemon_command ${OSPF_PORT} ${OSPF_PASSWORD} "show memory $*" + ;; + gen*) + daemon_command ${OSPF_PORT} ${OSPF_PASSWORD} "show ip ospf" + ;; + nei*) + shift; shift; + daemon_command ${OSPF_PORT} ${OSPF_PASSWORD} "show ip ospf neighbor $*" + ;; + dat*) + shift; shift; + daemon_command ${OSPF_PORT} ${OSPF_PASSWORD} "show ip ospf database $*" + ;; + int*) + daemon_command ${OSPF_PORT} ${OSPF_PASSWORD} "show ip ospf interface $3" + ;; + bor*) + daemon_command ${OSPF_PORT} ${OSPF_PASSWORD} "show ip ospf border-routers" + ;; + rou*) + daemon_command ${OSPF_PORT} ${OSPF_PASSWORD} "show ip ospf route" + ;; + esac ;; +esac diff --git a/config/quagga_ospfd/status_ospfd.php b/config/quagga_ospfd/status_ospfd.php new file mode 100644 index 00000000..7a4c66d2 --- /dev/null +++ b/config/quagga_ospfd/status_ospfd.php @@ -0,0 +1,129 @@ + + 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"); + +$pgtitle = "Quagga OSPF: Status"; +include("head.inc"); + +$control_script = "/root/quaggactl.sh"; + +/* List all of the commands as an index. */ +function listCmds() { + global $commands; + echo "
This status page includes the following information:\n"; + echo "\n"; +} + +function execCmds() { + global $commands; + for ($i = 0; isset($commands[$i]); $i++ ) { + doCmdT($commands[$i][0], $commands[$i][1]); + } +} + +/* Define a command, with a title, to be executed later. */ +function defCmdT($title, $command) { + global $commands; + $title = htmlspecialchars($title,ENT_NOQUOTES); + $commands[] = array($title, $command); +} + +function doCmdT($title, $command) { + echo "

\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "
" . $title . "
";		/* no newline after pre */
+
+	$execOutput = "";
+	$execStatus = "";
+	exec ($command . " 2>&1", $execOutput, $execStatus);
+	for ($i = 0; isset($execOutput[$i]); $i++) {
+		if ($i > 0) {
+			echo "\n";
+		}
+		echo htmlspecialchars($execOutput[$i],ENT_NOQUOTES);
+	}
+	echo "
\n"; +} + +?> + + + + + + + + + + + +
+ +
+
+ + + + +
+ +
+ + +
+
+
+
+ + + -- cgit v1.2.3