diff --git a/net/pfSense-pkg-udpbroadcastrelay/Makefile b/net/pfSense-pkg-udpbroadcastrelay/Makefile new file mode 100644 index 000000000000..07f679f6aaa8 --- /dev/null +++ b/net/pfSense-pkg-udpbroadcastrelay/Makefile @@ -0,0 +1,47 @@ +PORTNAME= pfSense-pkg-udpbroadcastrelay +PORTVERSION= 1.0 +PORTREVISION= 0 +CATEGORIES= net +MASTER_SITES= # empty +DISTFILES= # empty +EXTRACT_ONLY= # empty + +MAINTAINER= coreteam@pfsense.org +COMMENT= pfSense package UDP Broadcast Relay + +LICENSE= APACHE20 + +RUN_DEPENDS= udpbroadcastrelay>0:net/udpbroadcastrelay + +NO_BUILD= yes +NO_MTREE= yes + +SUB_FILES= pkg-install pkg-deinstall +SUB_LIST= PORTNAME=${PORTNAME} + +do-extract: + ${MKDIR} ${WRKSRC} + +do-install: + ${MKDIR} ${STAGEDIR}/etc/inc/priv + ${MKDIR} ${STAGEDIR}${PREFIX}/pkg/udpbroadcastrelay + ${MKDIR} ${STAGEDIR}${PREFIX}/www + ${MKDIR} ${STAGEDIR}${DATADIR} + + ${INSTALL_DATA} ${FILESDIR}/etc/inc/priv/udpbroadcastrelay.priv.inc \ + ${STAGEDIR}/etc/inc/priv + ${INSTALL_DATA} ${FILESDIR}${PREFIX}/pkg/udpbroadcastrelay.xml \ + ${STAGEDIR}${PREFIX}/pkg + ${INSTALL_DATA} ${FILESDIR}${PREFIX}/pkg/udpbroadcastrelay/udpbroadcastrelay.inc \ + ${STAGEDIR}${PREFIX}/pkg/udpbroadcastrelay + ${INSTALL_DATA} ${FILESDIR}${PREFIX}/www/udpbroadcastrelay.php \ + ${STAGEDIR}${PREFIX}/www + ${INSTALL_DATA} ${FILESDIR}${PREFIX}/www/udpbroadcastrelay_edit.php \ + ${STAGEDIR}${PREFIX}/www + ${INSTALL_DATA} ${FILESDIR}${DATADIR}/info.xml \ + ${STAGEDIR}${DATADIR} + + @${REINPLACE_CMD} -i '' -e "s|%%PKGVERSION%%|${PKGVERSION}|" \ + ${STAGEDIR}${DATADIR}/info.xml + +.include diff --git a/net/pfSense-pkg-udpbroadcastrelay/files/etc/inc/priv/udpbroadcastrelay.priv.inc b/net/pfSense-pkg-udpbroadcastrelay/files/etc/inc/priv/udpbroadcastrelay.priv.inc new file mode 100644 index 000000000000..5b6a2056525a --- /dev/null +++ b/net/pfSense-pkg-udpbroadcastrelay/files/etc/inc/priv/udpbroadcastrelay.priv.inc @@ -0,0 +1,32 @@ + diff --git a/net/pfSense-pkg-udpbroadcastrelay/files/pkg-deinstall.in b/net/pfSense-pkg-udpbroadcastrelay/files/pkg-deinstall.in new file mode 100644 index 000000000000..83d1c3dcab9e --- /dev/null +++ b/net/pfSense-pkg-udpbroadcastrelay/files/pkg-deinstall.in @@ -0,0 +1,3 @@ +#!/bin/sh + +/usr/local/bin/php -f /etc/rc.packages %%PORTNAME%% ${2} diff --git a/net/pfSense-pkg-udpbroadcastrelay/files/pkg-install.in b/net/pfSense-pkg-udpbroadcastrelay/files/pkg-install.in new file mode 100644 index 000000000000..c192d05db62d --- /dev/null +++ b/net/pfSense-pkg-udpbroadcastrelay/files/pkg-install.in @@ -0,0 +1,7 @@ +#!/bin/sh + +if [ "${2}" != "POST-INSTALL" ]; then + exit 0 +fi + +${PKG_ROOTDIR}/usr/local/bin/php -f ${PKG_ROOTDIR}/etc/rc.packages %%PORTNAME%% ${2} diff --git a/net/pfSense-pkg-udpbroadcastrelay/files/usr/local/pkg/udpbroadcastrelay.xml b/net/pfSense-pkg-udpbroadcastrelay/files/usr/local/pkg/udpbroadcastrelay.xml new file mode 100644 index 000000000000..b3436a154673 --- /dev/null +++ b/net/pfSense-pkg-udpbroadcastrelay/files/usr/local/pkg/udpbroadcastrelay.xml @@ -0,0 +1,59 @@ + + + + + + + + udpbroadcastrelay + %%PKGVERSION%% + Services/UDP Broadcast Relay + /usr/local/pkg/udpbroadcastrelay/udpbroadcastrelay.inc + + UDP Broadcast Relay +
Services
+ /udpbroadcastrelay.php +
+ + udpbroadcastrelay + udpbroadcastrelay.sh + udpbroadcastrelay + UDP Broadcast Relay + + + + + plugin_carp + + + + + + + + +
diff --git a/net/pfSense-pkg-udpbroadcastrelay/files/usr/local/pkg/udpbroadcastrelay/udpbroadcastrelay.inc b/net/pfSense-pkg-udpbroadcastrelay/files/usr/local/pkg/udpbroadcastrelay/udpbroadcastrelay.inc new file mode 100644 index 000000000000..1ebd991ac877 --- /dev/null +++ b/net/pfSense-pkg-udpbroadcastrelay/files/usr/local/pkg/udpbroadcastrelay/udpbroadcastrelay.inc @@ -0,0 +1,512 @@ + 'udpbroadcastrelay.sh', + 'rc' => '/usr/local/etc/rc.d/udpbroadcastrelay.sh', + 'daemon' => '/usr/local/sbin/udpbroadcastrelay', + 'services' => '/usr/local/etc/udpbroadcastrelay/services/' + ); +} + +/** + * Validates the given settings. + * + * @param array $settings Settings to validate; can be all settings, or a single instance. + * @param bool $is_instance If settings is for a single instance, check for duplicate instances + * @param bool $idx (Optional) Configuration array index of the given instance + * @param array $available_interfaces (Optional) Validate settings based on the given interface array keyed by friendly name + * + * @throws Exception If the given settings to validate are empty and not an array + * @return array List of strings describing the validation errors + * @return false No errors found; settings are valid. + */ +function udpbr_validate_config($settings, $is_instance, $idx = null, $available_interfaces = array()) { + if (empty($settings)) { + return null; + } elseif (!is_array($settings) || (!is_numericint($idx) && null !== $idx)) { + throw new Exception('Cannot validate settings with given parameters.'); + } + + if ($is_instance) { + $pconfig = array('item' => array()); + $pconfig['item'][] = $settings; + } else { + $pconfig = $settings; + } + + $input_errors = array(); + $input_errors_prefix = gettext('General: '); + // Validate service 'enable' option + if (isset($pconfig['enable']) && !empty($pconfig['enable'])) { + $input_errors[] = sprintf('%1$s%2$s', $input_errors_prefix, gettext('"Enable" property set incorrectly.')); + } + // Validate service 'Track CARP Status' option + if (!empty($pconfig['carpstatusvid']) && $pconfig['carpstatusvid'] != 'none') { + $available_carpstatusvid = udpbr_get_carp_list(); + if (!array_key_exists($pconfig['carpstatusvid'], $available_carpstatusvid)) { + $input_errors[] = sprintf('%1$s%2$s', $input_errors_prefix, gettext('Invalid "Track CARP Status" option.')); + } + } + + if (!empty($pconfig['item']) && is_array($pconfig['item'])) { + // Check for duplicate instances when validating instance settings + if ($is_instance) { + $saved_instances = config_get_path('installedpackages/udpbroadcastrelay/config/0/item', []); + } + + if (empty($available_interfaces) || !is_array($available_interfaces)) { + $available_interfaces = udpbr_get_interfaces_sorted(); + } + foreach ($pconfig['item'] as $pidx => $pinstance) { + if (!$is_instance) { + $idx = $pidx; + } elseif (!is_numericint($idx)) { + $idx = 'new'; + } + $input_errors_prefix = gettext(sprintf('Instance [%s]: ', $idx)); + + // Validate instance ID + if (!empty($pinstance['id'])) { + if (!($pinstance['id'] >= 1 && $pinstance['id'] <= 63)) { + $input_errors[] = sprintf('%1$s%2$s', $input_errors_prefix, gettext('Invalid instance ID given.')); + } + } else { + $input_errors[] = sprintf('%1$s%2$s', $input_errors_prefix, gettext('An instance ID number from 1 to 63 is required.')); + } + + // Validate instance 'enable' option + if (isset($instance['enable']) && !empty($instance['enable'])) { + $input_errors[] = sprintf('%1$s%2$s', $input_errors_prefix, gettext('"Enable" property set incorrectly.')); + } + + // Validate instance port + if (!empty($pinstance['port'])) { + if (!($pinstance['port'] >= 1 && $pinstance['port'] <= 65535)) { + $input_errors[] = sprintf('%1$s%2$s', $input_errors_prefix, gettext('Invalid port number given.')); + } + } else { + $input_errors[] = sprintf('%1$s%2$s', $input_errors_prefix, gettext('A port number from 1 to 65535 is required.')); + } + + // Validate instance selected interfaces + $interfaces = explode(',', $pinstance['interfaces']); + if (is_array($interfaces) && count($interfaces) >= 2) { + if (((bool) array_intersect_key(array_flip($interfaces), $available_interfaces)) == false) { + $input_errors[] = sprintf('%1$s%2$s', $input_errors_prefix, gettext('Invalid interface(s) selected.')); + } + } else { + $input_errors[] = sprintf('%1$s%2$s', $input_errors_prefix, gettext('At least two interfaces must be selected.')); + } + + // Validate instance spoof option + if (!empty($pinstance['spoof']) || $pinstance['spoof'] == '0') { + if (!in_array($pinstance['spoof'], array(0,1,2))) { + $input_errors[] = sprintf('%1$s%2$s', $input_errors_prefix, gettext('Invalid spoof option selected.')); + } + } + + // Validate instance multicast address + if (!empty($pinstance['multicast'])) { + if (!is_ipaddr($pinstance['multicast'])) { + $input_errors[] = sprintf('%1$s%2$s', $input_errors_prefix, gettext('Invalid multicast IP address given.')); + } + } + + // Check for duplicates + if ($is_instance && isset($pinstance['enable'])) { + $pinstance_interfaces = explode(',', $pinstance['interfaces']); + foreach ($saved_instances as $saved_instance_idx => $saved_instance) { + $input_errors_prefix = gettext(sprintf('Instance [%s]: ', $saved_instance_idx)); + if (isset($saved_instance['enable']) && $idx != $saved_instance_idx) { + if ($pinstance['id'] == $saved_instance['id']) { + $input_errors[] = sprintf('%1$s%2$s', $input_errors_prefix, gettext('Duplicate ID found on another instance.')); + } + if ($pinstance['id'] != $saved_instance['id'] && $pinstance['port'] == $saved_instance['port'] && + !empty(array_intersect($pinstance_interfaces, explode(',', $saved_instance['interfaces'])))) { + $input_errors[] = sprintf('%1$s%2$s', $input_errors_prefix, gettext('Duplicate port found on an instance with overlaping interfaces.')); + } + } + } + } + } + } + + if (empty($input_errors)) { + return false; + } else { + return $input_errors; + } +} + +/** + * Generates the shell command string needed to run the given instance configuraiton. + * + * @param array $instance Configuration for a single instance + * + * @return string Full shell command + */ +function udpbr_get_command($instance) { + global $udpbr_paths; + $interfaces = explode(',', $instance['interfaces']); + + $command = sprintf('%1$s --id %2$s --port %3$s', $udpbr_paths['daemon'], $instance['id'], $instance['port']); + foreach ($interfaces as $value) { + $command .= sprintf(' --dev %s', $value); + } + if (!empty($instance['multicast'])) { + $command .= sprintf(' --multicast %s', $instance['multicast']); + } + if ($instance['spoof'] == '1') { + $command .= ' -s 1.1.1.1'; + } elseif ($instance['spoof'] == '2') { + $command .= ' -s 1.1.1.2'; + } + $command .= ' -f'; + + return escapeshellcmd($command); +} + +/** + * Initializes the configuration path; creates the service script, and starts/stops the service as needed. + * + * @return null + */ +function udpbr_resync() { + global $udpbr_paths; + $cpath = 'installedpackages/udpbroadcastrelay/config/0'; + + if (is_service_running('udpbroadcastrelay')) { + syslog(LOG_NOTICE, "Stopping service udpbroadcastrelay"); + stop_service('udpbroadcastrelay'); + } + + $run_commands = array(); + $instances = udpbr_get_settings(true); + if (!empty($instances)) { + $available_interfaces = udpbr_get_interfaces_sorted(); + $available_interfaces_ports = array_flip(convert_real_interface_to_friendly_interface_name_fast()); + foreach ($instances as $instance_idx => $instance) { + try { + if (udpbr_validate_config($instance, true, $instance_idx, $available_interfaces)) { + continue; + } + } catch (Exception $e) { + syslog(LOG_ERR, sprintf('ERROR validating UDP Broadcast Relay settings: %s', $e->getMessage())); + continue; + } + + if (!isset($instance['enable'])) { + continue; + } + + // Use the interface's real name instead of its friendly name + $instance_interfaces = array(); + foreach (explode(',', $instance['interfaces']) as $i) { + if (array_key_exists($i, $available_interfaces_ports)) { + $instance_interfaces[] = $available_interfaces_ports[$i]; + } else { + continue 2; + } + } + $instance['interfaces'] = implode(',', $instance_interfaces); + + $run_commands[] = udpbr_get_command($instance); + } + } + if (empty($run_commands) || !config_path_enabled($cpath)) { + unlink_if_exists($udpbr_paths['rc']); + return; + } + + /* Write the rc script */ + $start = implode(PHP_EOL, $run_commands); + $stop = "/usr/bin/killall -q udpbroadcastrelay"; + write_rcfile(array( + "file" => $udpbr_paths['rc_filename'], + "start" => $start, + "stop" => $stop + ) + ); + + if (platform_booting()) { + return; + } + + if (config_path_enabled($cpath)) { + /* Start/Restart UDP Broadcast Relay, if a CARP VIP is set, check its status and act appropriately. */ + $carpstatusvid = config_get_path($cpath . '/carpstatusvid'); + if (!empty($carpstatusvid) || $carpstatusvid != "none") { + $status = get_carp_interface_status($carpstatusvid); + switch (strtoupper($status)) { + // Stop the service if the VIP is in BACKUP or INIT state. + case "BACKUP": + case "INIT": + syslog(LOG_NOTICE, "Stopping service udpbroadcastrelay (CARP BACKUP/INIT)"); + stop_service("udpbroadcastrelay"); + break; + // Start the service if the VIP is MASTER state. + case "MASTER": + // Assume it's up if the status can't be determined. + default: + syslog(LOG_NOTICE, "Starting service udpbroadcastrelay"); + start_service('udpbroadcastrelay'); + break; + } + } else { + syslog(LOG_NOTICE, "Starting service udpbroadcastrelay"); + start_service('udpbroadcastrelay'); + } + } +} + +/** + * Stops the service and removes the service script. + * + * @return null + */ +function udpbr_deinstall() { + global $udpbr_paths; + if (is_service_running('udpbroadcastrelay')) { + syslog(LOG_NOTICE, "Stopping service udpbroadcastrelay"); + stop_service('udpbroadcastrelay'); + } + + unlink_if_exists($udpbr_paths['rc']); +} + +/** + * Get the available CARP VIPs on the system. + * + * @return array List of strings keyed by the VIP ID + */ +function udpbr_get_carp_list() { + $list = array(); + $list['none'] = 'none'; + $carplist = get_configured_vip_list("all", VIP_CARP); + foreach ($carplist as $vid => $vaddr) { + $vip = get_configured_vip($vid); + $list[$vid] = "{$vaddr} (vhid: {$vip['vhid']})"; + } + return ($list); +} + +/** + * Starts or stops the service based on the CARP transition + * + * @param array $pluginparams List of plugin parameters + * + * @return null + */ +function udpbroadcastrelay_plugin_carp($pluginparams) { + $carpstatusvid = config_get_path('installedpackages/udpbroadcastrelay/config/0/carpstatusvid'); + + /* If there is no "Track CARP Status" IP address selected, then stop */ + if (empty($carpstatusvid) || $carpstatusvid == "none") { + return null; + } + /* Locate the VIP and match it against the configured "Track CARP Status" IP address */ + list($vhid, $iface) = explode("@", trim($pluginparams['interface'])); + $friendly = convert_real_interface_to_friendly_interface_name($iface); + $vip = get_configured_vip($carpstatusvid); + if (($vip['vhid'] != $vhid) || ($vip['interface'] != $friendly)) { + /* This is not the VIP we're looking for, move along. */ + return null; + } + /* Start or stop the service as needed based on the CARP transition. */ + if ($pluginparams['event'] == "rc.carpmaster") { + syslog(LOG_NOTICE, "Starting service udpbroadcastrelay"); + start_service("udpbroadcastrelay"); + } elseif ($pluginparams['event'] == "rc.carpbackup") { + syslog(LOG_NOTICE, "Stopping service udpbroadcastrelay (CARP BACKUP/INIT)"); + stop_service("udpbroadcastrelay"); + } +} + +/** + * Generates a list of interfaces and their descriptions with port names, sorted by their friendly names. + * For example: 'lan' => 'LAN (igb1)' or simply 'lan' => 'LAN' + * + * @param bool $description_only (Optional) When true, excludes the port name from the interface description + * + * @return array List of interfaces and their description, keyed by the interface's friendly name. + */ +function udpbr_get_interfaces_sorted($description_only = false) { + // Get all interfaces and their descriptions + $i_ports = get_interface_arr(); + $i_names = convert_real_interface_to_friendly_interface_name_fast(); + $i_descriptions = get_configured_interface_with_descr(true); + + /* Group interfaces and their descriptions in a consistent order */ + foreach ($i_names as $i => $n) { + if (array_search($i, $i_ports, true) === false) { + // Ignore interfaces that are not found on the system + continue; + } + $i_list_assigned[$n] = $i; + } + $i_list_assigned_append = $i_list_assigned; + $i_list_unassigned = array(); + $i_list_unassigned_append = array(); + foreach ($i_ports as $i) { + if (in_array($i, array('pfsync0', 'pflog0', 'enc0', 'lo0'))) { + // Ignore special interfaces + continue; + } + + $append = false; + $assigned = false; + $description = sprintf('unassigned (%s)', $i); + + if (preg_match('/(ovpn[sc]\d+|tun_wg\d+|ipsec\d+)/', $i)) { + $append = true; + } + + // Set the interface description + if (!$assigned && array_key_exists($i, $i_names)) { + if (array_key_exists($i_names[$i], $i_descriptions)) { + $assigned = true; + if ($description_only) { + $description = sprintf('%1$s', $i_descriptions[$i_names[$i]]); + } else { + $description = sprintf('%1$s (%2$s)', $i_descriptions[$i_names[$i]], $i); + } + } + } + + // Save the interface to the respective group + if ($assigned && (get_interface_ip($i_names[$i]) || get_interface_ipv6($i_names[$i]))) { + if ($append) { + $i_list_assigned_append[$i_names[$i]] = $description; + unset($i_list_assigned[$i_names[$i]]); + } else { + $i_list_assigned[$i_names[$i]] = $description; + unset($i_list_assigned_append[$i_names[$i]]); + } + } else { + unset($i_list_assigned[$i_names[$i]]); + unset($i_list_assigned_append[$i_names[$i]]); + } + } + + /* return ordered interface list */ + return array_merge($i_list_assigned, $i_list_assigned_append); +} + +/** + * Fetches the configuration for the service and or instance(s). + * + * @param bool $instancesonly (Optional) When true, returns a list of all instances configuration + * @param int $idx (Optional) Return the instance stored at the given configuration array index + * + * @return false When no settings are configured + * @return array All configuration + * @return array List of all instances configuration + * @return array Instance configuration in the given configuration array index + */ +function udpbr_get_settings($instancesonly = false, $idx = false) { + $cpath = 'installedpackages/udpbroadcastrelay/config/0'; + + // Return all settings config + if (!$instancesonly) { + return config_get_path($cpath, false); + } + + // Return all instances config + if ($idx === false) { + return config_get_path($cpath . '/item', false); + } + + // Return the instance config for the given idx + if (is_numericint($idx)) { + return config_get_path($cpath . "/item/{$idx}", false); + } + + // No instances configured + return false; +} + +/** + * Writes the configuration for the given instance array, and optionally removes it. + * + * @param array $instance Configuration for a single instance. Set as null when removing. + * @param bool $is_new_entry Signifies to save the given instance as a new entry + * @param int $idx (Optional) Configuration array index of instance to update or remove + * + * @return null + */ +function udpbr_set_instance($instance, $is_new_entry, $idx = null) { + // Instances config path + $cpath = 'installedpackages/udpbroadcastrelay/config/0/item'; + + if (is_array($instance) && $is_new_entry) { + // Save a new instance config + $pkg_instances_config = config_get_path($cpath, []); + $pkg_instances_config[] = $instance; + config_set_path($cpath, $pkg_instances_config); + } elseif (is_numericint($idx)) { + $cpath = sprintf('%1$s/%2$s', $cpath, $idx); + if (is_array($instance)) { + // Update existing instance config + if (!empty(config_get_path($cpath))) { + config_set_path($cpath, $instance); + } + } elseif (empty($instance)) { + // Remove existing instance config + if (!empty(config_get_path($cpath))) { + config_del_path($cpath); + } + } + } +} + +/** + * Writes the configuration for service's general settings. Does not include instance configuration. + * + * @param array $settings (Optional) List of general settings + * + * @return null + */ +function udpbr_set_settings($settings = false) { + $cpath = 'installedpackages/udpbroadcastrelay/config/0'; + + if ($settings !== false) { + // Save the general settings + if (isset($settings['enable'])) { + config_set_path($cpath . '/enable', ''); + } else { + config_del_path($cpath . '/enable'); + } + if (isset($settings['carpstatusvid'])) { + config_set_path($cpath . '/carpstatusvid', $settings['carpstatusvid']); + } + } +} + +?> \ No newline at end of file diff --git a/net/pfSense-pkg-udpbroadcastrelay/files/usr/local/share/pfSense-pkg-udpbroadcastrelay/info.xml b/net/pfSense-pkg-udpbroadcastrelay/files/usr/local/share/pfSense-pkg-udpbroadcastrelay/info.xml new file mode 100644 index 000000000000..798aab5102cf --- /dev/null +++ b/net/pfSense-pkg-udpbroadcastrelay/files/usr/local/share/pfSense-pkg-udpbroadcastrelay/info.xml @@ -0,0 +1,11 @@ + + + + UDP Broadcast Relay + udpbroadcastrelay + + https://www.freshports.org/net/udpbroadcastrelay/ + %%PKGVERSION%% + udpbroadcastrelay.xml + + diff --git a/net/pfSense-pkg-udpbroadcastrelay/files/usr/local/www/udpbroadcastrelay.php b/net/pfSense-pkg-udpbroadcastrelay/files/usr/local/www/udpbroadcastrelay.php new file mode 100644 index 000000000000..6e7499d232d1 --- /dev/null +++ b/net/pfSense-pkg-udpbroadcastrelay/files/usr/local/www/udpbroadcastrelay.php @@ -0,0 +1,223 @@ +getMessage()}"); +} + +// Save the configuration and apply changes +if (isset($_POST['save']) && empty($input_errors)) { + udpbr_set_settings($pconfig); + write_config("UDP Broadcast Relay pkg: saved general settings."); + udpbr_resync(); +} + +$pgtitle = array(gettext('Services'), gettext('UDP Broadcast Relay')); +$pglinks = array('', 'udpbroadcastrelay.php'); +include_once("head.inc"); + +// Show input validation errors +if (!empty($input_errors)) { + print_input_errors($input_errors); +} + +// Show save messages +if (isset($_POST['save']) && empty($input_errors)) { + print_info_box(gettext('Saved general settings.'), 'success'); +} elseif (isset($_GET['saved'])) { + print_info_box(gettext('Saved settings.'), 'success'); +} + +// General Settings form +$form = new Form; +$section = new Form_Section('General Settings'); +$section->addInput(new Form_Checkbox( + 'enable', + 'Enable', + 'Enable the UDP Broadcast Relay service.', + isset($pconfig['enable']) +)); +$section->addInput(new Form_Select( + 'carpstatusvid', + "Track CARP Status", + $pconfig['carpstatusvid'], + udpbr_get_carp_list() +))->setHelp('Tracks the CARP status of the selected CARP VIP. The service will only run when the selected VIP is in the MASTER state.')->setWidth(5); +$form->add($section); + +print($form); + +// Configured Instances form +?> + +
+

+
+
+ + + + + + + + + + + + + + $instance): ?> + class="disabled"> + + + + + + + + + + + + +
+ + + + + + + + + + + +
+ + + + + 0): ?> + + +
+
+
+
+ + + + '', + 'description' => '', + 'port' => '', + 'interfaces' => '', + 'spoof' => '', + 'multicast' => '' + ); +} + +if (isset($_POST['save'])) { + $pconfig['id'] = $_POST['id']; + if (isset($_POST['enable'])) { + $pconfig['enable'] = ''; + } elseif (isset($pconfig['enable'])) { + unset($pconfig['enable']); + } + $pconfig['description'] = mb_convert_encoding($_POST['description'],"HTML-ENTITIES","auto"); + $pconfig['port'] = $_POST['port']; + $pconfig['interfaces'] = implode(',', $_POST['interfaces']); + $pconfig['spoof'] = $_POST['spoof']; + $pconfig['multicast'] = $_POST['multicast']; +} + +// Do input validation when saving or editing an existing configuration +if (isset($_POST['save']) || !$is_new_entry) { + try { + $input_errors = udpbr_validate_config($pconfig, true, $idx); + } catch (Exception $e) { + $input_errors = array("{$e}"); + } + + // Save the configuration, apply changes, and redirect with save message + if (isset($_POST['save']) && empty($input_errors)) { + udpbr_set_instance($pconfig, $is_new_entry, $idx); + write_config("UDP Broadcast Relay pkg: saved instance."); + udpbr_resync(); + header("Location: udpbroadcastrelay.php?saved"); + exit; + } +} + +$pgtitle = array(gettext('Services'), gettext('UDP Broadcast Relay'), gettext('Edit')); +$pglinks = array('', 'udpbroadcastrelay.php', '@self'); +include("head.inc"); + +// Show input validation errors +if (!empty($input_errors)) { + print_input_errors($input_errors); +} + +// Form variables +$form_interfaces_available = udpbr_get_interfaces_sorted(); +$form_spoof_options = array( + 0 => 'Keep Original (default)', + 1 => 'Use Interface Address and Destination Port', + 2 => 'Use Interface Address only' +); + +$form = new Form; +$section = new Form_Section('Instance Settings'); +$section->addInput(new Form_Checkbox( + 'enable', + 'Enable', + 'Enable this instance.', + isset($pconfig['enable']) +)); +$section->addInput(new Form_Input( + 'description', + 'Description', + 'text', + $pconfig['description'] +))->setHelp('A description for administrative reference (not parsed).'); +$section->addInput(new Form_Select( + 'interfaces', + '*Network Interfaces', + (explode(',', $pconfig['interfaces'])), + $form_interfaces_available, + true +))->addClass('general', 'resizable')->setHelp('Interfaces to receive and transmit packets on. Must select at least 2.')->setWidth(5); +$section->addInput(new Form_Select( + 'spoof', + "Spoof Source", + $pconfig['spoof'], + $form_spoof_options +))->setHelp('Spoof the source IP address and/or port when relaying packets.')->setWidth(5); +$group = new Form_Group(''); +$group->add(new Form_Input( + 'id', + 'Instance ID', + null, + $pconfig['id'], + array('type' => 'number', 'min' => 1, 'max' => 63, 'step' => 1) +))->setHelp('A unique number between instances (1-63).')->setWidth(2); +$group->add(new Form_Input( + 'port', + 'UDP Port', + null, + $pconfig['port'], + array('type' => 'number', 'min' => 1, 'max' => 65535, 'step' => 1) +))->setHelp('Destination UDP port to listen on (1-65535).')->setWidth(2); +$group->add(new Form_IpAddress( + 'multicast', + 'IP Address', + $pconfig['multicast'], + 'V4' +))->setHelp('Multicast group to relay packets on (optional).')->setWidth(2); +$section->add($group); +$form->add($section); + +print($form); + +include("foot.inc"); diff --git a/net/pfSense-pkg-udpbroadcastrelay/pkg-descr b/net/pfSense-pkg-udpbroadcastrelay/pkg-descr new file mode 100644 index 000000000000..8cd3637840ea --- /dev/null +++ b/net/pfSense-pkg-udpbroadcastrelay/pkg-descr @@ -0,0 +1,3 @@ +A GUI for UDP Broadcast Relay. This program listens for UDP broadcast packets and retransmits on additional interfaces. + +WWW: https://www.freshports.org/net/udpbroadcastrelay/ diff --git a/net/pfSense-pkg-udpbroadcastrelay/pkg-plist b/net/pfSense-pkg-udpbroadcastrelay/pkg-plist new file mode 100644 index 000000000000..438e0312e212 --- /dev/null +++ b/net/pfSense-pkg-udpbroadcastrelay/pkg-plist @@ -0,0 +1,8 @@ +/etc/inc/priv/udpbroadcastrelay.priv.inc +pkg/udpbroadcastrelay.xml +pkg/udpbroadcastrelay/udpbroadcastrelay.inc +%%DATADIR%%/info.xml +www/udpbroadcastrelay.php +www/udpbroadcastrelay_edit.php +@dir /etc/inc/priv +@dir /etc/inc