From 90db8f4d0fa22063d1a8c06ba4063d3fa7a79a11 Mon Sep 17 00:00:00 2001 From: Franco Fichtner Date: Fri, 22 Jul 2022 10:54:55 +0200 Subject: [PATCH] interfaces: widen and improve ifctl use We do want to eventually lean on exclusive ifctl use in order to be able to improve logic in ifctl or make adjustments really easy in the future without missing a spot (e.g. adding scope to link-local routers). --- src/etc/inc/interfaces.inc | 12 +-- src/etc/inc/system.inc | 47 +++++++----- src/man/man8/ifctl.8 | 20 +++-- src/opnsense/scripts/interfaces/nameserver.sh | 75 +++++++++++++------ 4 files changed, 100 insertions(+), 54 deletions(-) diff --git a/src/etc/inc/interfaces.inc b/src/etc/inc/interfaces.inc index 475108faf..c85647339 100644 --- a/src/etc/inc/interfaces.inc +++ b/src/etc/inc/interfaces.inc @@ -932,13 +932,8 @@ function interface_bring_down($interface = "wan", $ifacecfg = false) } /* clear stale state files associated with this interface */ - @unlink("/tmp/{$realifv6}_nameserverv6"); - @unlink("/tmp/{$realifv6}_prefixv6"); - @unlink("/tmp/{$realifv6}_routerv6"); - @unlink("/tmp/{$realifv6}_searchdomainv6"); - @unlink("/tmp/{$realif}_nameserver"); - @unlink("/tmp/{$realif}_router"); - @unlink("/tmp/{$realif}_searchdomain"); + mwexecf('/usr/local/sbin/ifctl -4c -i %s', $realif); + mwexecf('/usr/local/sbin/ifctl -6c -i %s', $realifv6); } function interfaces_ptpid_used($ptpid) @@ -3930,8 +3925,7 @@ function get_interfaces_info($include_unlinked = false) } } - /* XXX there are more magic files */ - $aux = @file_get_contents("/tmp/{$ifinfo['ifv6']}_prefixv6"); + $aux = trim(shell_exec(exec_safe('/usr/local/sbin/ifctl -6pi %s', $ifinfo['ifv6']))); if (!empty($aux)) { $ifinfo['prefixv6'] = $aux; } diff --git a/src/etc/inc/system.inc b/src/etc/inc/system.inc index ca278a48d..9361427f5 100644 --- a/src/etc/inc/system.inc +++ b/src/etc/inc/system.inc @@ -294,13 +294,16 @@ function get_zoneinfo() function get_searchdomains() { - $search_list = glob('/tmp/*_searchdomain*'); $syscfg = config_read_array('system'); $master_list = []; + $search_list = []; - if (!isset($syscfg['dnsallowoverride'])) { - /* do not return domains as required by configuration */ - $search_list = []; + if (isset($syscfg['dnsallowoverride'])) { + /* return domains as required by configuration */ + $list = trim(shell_exec('/usr/local/sbin/ifctl -sl')); + if (!empty($list)) { + $search_list = explode("\n", $list); + } } if (is_array($search_list)) { @@ -325,22 +328,29 @@ function get_nameservers($interface = null, $with_gateway = false) global $config; $gateways = new \OPNsense\Routing\Gateways(legacy_interfaces_details()); - $dns_lists = glob('/tmp/*_nameserver*'); $syscfg = config_read_array('system'); $exclude_interfaces = []; $master_list = []; + $dns_lists = []; if (!empty($interface)) { /* only acquire servers provided for this interface */ $realif = get_real_interface($interface); $realifv6 = get_real_interface($interface, 'inet6'); - $dns_lists = [ - "/tmp/{$realif}_nameserver", - "/tmp/{$realifv6}_nameserverv6", - ]; - } elseif (!isset($syscfg['dnsallowoverride'])) { - /* do not return dynamic servers as required by configuration */ - $dns_lists = []; + $list = trim(shell_exec(exec_safe('/usr/local/sbin/ifctl -4nli %s', $realif))); + if (!empty($list)) { + $dns_lists[] = $list; + } + $list = trim(shell_exec(exec_safe('/usr/local/sbin/ifctl -6nli %s', $realifv6))); + if (!empty($list)) { + $dns_lists[] = $list; + } + } elseif (isset($syscfg['dnsallowoverride'])) { + /* return dynamic servers as required by configuration */ + $list = trim(shell_exec('/usr/local/sbin/ifctl -nl')); + if (!empty($list)) { + $dns_lists = explode("\n", $list); + } } if (isset($syscfg['dnsallowoverride_exclude'])) { @@ -355,7 +365,8 @@ function get_nameservers($interface = null, $with_gateway = false) foreach ($dns_lists as $fdns) { /* inspect dynamic servers registered in the system files */ - $intf = explode('_', basename($fdns))[0]; + $intf = explode('_', basename($fdns), 2); + $intf[1] = strpos($intf[1], 'v6') === false ? '4' : '6'; if (in_array($intf, $exclude_interfaces)) { continue; } @@ -365,10 +376,12 @@ function get_nameservers($interface = null, $with_gateway = false) continue; } - /* router file is available for connectivity creating nameserver files */ - $gw = trim(@file_get_contents(str_replace('_nameserver', '_router', $fdns))); - if (is_linklocal($gw) && strpos($gw, '%') === false) { - $gw .= "%{$intf}"; + if ($with_gateway) { + /* router file is available for connectivity creating nameserver files */ + $gw = trim(shell_exec(exec_safe('/usr/local/sbin/ifctl -%s -ri %s', [$intf[1], $intf[0]]))); + if (is_linklocal($gw) && strpos($gw, '%') === false) { + $gw .= "%{$intf[0]}"; + } } foreach ($contents as $dns) { diff --git a/src/man/man8/ifctl.8 b/src/man/man8/ifctl.8 index 752b751f0..83d478740 100644 --- a/src/man/man8/ifctl.8 +++ b/src/man/man8/ifctl.8 @@ -24,7 +24,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd March 18, 2022 +.Dd July 22, 2022 .Dt IFCTL 8 .Os .Sh NAME @@ -33,15 +33,16 @@ .Sh SYNOPSIS .Nm .Op Fl i Ar device +.Op Fl 46 .Op Fl nprs -.Op Fl d -.Op Fl a Ar data +.Op Fl a Ar data | Fl c | Fl d | Fl l .Sh DESCRIPTION The .Nm utility will display or modify network device related data used by dynamic connections. -If neither +If one of +.Sq Fl c , .Sq Fl d or .Sq Fl a @@ -55,14 +56,16 @@ This is the default. .It Fl 6 Use IPv6 mode. .It Fl a -Append data to the currently selected device information. +Append data to the currently selected device data. The option can be used multiple times in the same command invoke to append data at once. Note that .Sq Fl d will be executed first when given in the same command invoke. +.It Fl c +Clear all registed data of the selected device. .It Fl d -Delete the data of the currently selected device information. +Delete the specified data of the selected device. .It Fl i Ar device Select the .Ar device @@ -70,6 +73,11 @@ to operate on. If none was given .Nm list the available devices. +.It Fl l +List mode turns the output into the storage files available for reading. +For implementational reasons the address family selector is ignored when +not using the interface option +.Sq Fl i . .It Fl n Use name server mode. This is the default. diff --git a/src/opnsense/scripts/interfaces/nameserver.sh b/src/opnsense/scripts/interfaces/nameserver.sh index c62f28062..4edc90808 100755 --- a/src/opnsense/scripts/interfaces/nameserver.sh +++ b/src/opnsense/scripts/interfaces/nameserver.sh @@ -23,9 +23,8 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. +DO_COMMAND= DO_CONTENTS= -DO_DELETE= -DO_MODE= DO_VERBOSE= AF= @@ -33,10 +32,22 @@ MD= EX= IF= +flush_routes() +{ + if [ "${MD}" != "nameserver" -o ! -f "${FILE}" ]; then + return + fi + + for CONTENT in $(cat ${FILE}); do + # flush routes here to make sure they are recycled properly + route delete -${AF} "${CONTENT}" + done +} + # default to IPv4 with nameserver mode set -- -4 -n ${@} -while getopts 46a:di:nprsV OPT; do +while getopts 46a:cdi:lnprsV OPT; do case ${OPT} in 4) AF=inet @@ -47,28 +58,31 @@ while getopts 46a:di:nprsV OPT; do EX=v6 ;; a) + DO_COMMAND="-a" DO_CONTENTS="${DO_CONTENTS} ${OPTARG}" ;; + c) + MD="nameserver prefix router searchdomain" + ;; d) - DO_DELETE="-d" + DO_COMMAND="-d" ;; i) IF=${OPTARG} ;; + l) + DO_COMMAND="-l" + ;; n) - DO_MODE="-n" MD="nameserver" ;; p) - DO_MODE="-p" MD="prefix" ;; r) - DO_MODE="-r" MD="router" ;; s) - DO_MODE="-s" MD="searchdomain" ;; V) @@ -85,6 +99,29 @@ if [ -n "${DO_VERBOSE}" ]; then set -x fi +if [ "${DO_COMMAND}" = "-c" ]; then + if [ -z "${IF}" ]; then + echo "Clearing requires interface option" >&2 + exit 1 + fi + + # iterate through possible files + for MD in nameserver prefix router searchdomain; do + FILE="/tmp/${IF}_${MD}${EX}" + flush_routes + rm -f ${FILE} + done + + exit 0 +elif [ "${DO_COMMAND}" = "-l" ]; then + if [ -z "${IF}" ]; then + EX="*" + IF="*" + fi + find -s /tmp -name "${IF}_${MD}${EX}" + exit 0 +fi + FILE="/tmp/${IF:-*}_${MD}${EX}" if [ -z "${IF}" ]; then @@ -98,20 +135,14 @@ if [ -z "${IF}" ]; then exit 0 fi -if [ -n "${DO_DELETE}" ]; then - if [ "${DO_MODE}" = "-n" -a -f ${FILE} ]; then - for CONTENT in $(cat ${FILE}); do - # flush routes here to make sure they are recycled properly - route delete -${AF} "${CONTENT}" - done - fi +if [ "${DO_COMMAND}" = "-d" ]; then + flush_routes rm -f ${FILE} -fi - -for CONTENT in ${DO_CONTENTS}; do - echo "${CONTENT}" >> ${FILE} -done - -if [ -z "${DO_CONTENTS}${DO_DELETE}" -a -f ${FILE} ]; then +elif [ "${DO_COMMAND}" = "-a" ]; then + for CONTENT in ${DO_CONTENTS}; do + echo "${CONTENT}" >> ${FILE} + done +# if nothing else could be done display data +elif [ -f ${FILE} ]; then cat ${FILE} fi