summaryrefslogtreecommitdiffstats
path: root/bin/tests/system/conf.sh.common
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 15:59:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 15:59:48 +0000
commit3b9b6d0b8e7f798023c9d109c490449d528fde80 (patch)
tree2e1c188dd7b8d7475cd163de9ae02c428343669b /bin/tests/system/conf.sh.common
parentInitial commit. (diff)
downloadbind9-3b9b6d0b8e7f798023c9d109c490449d528fde80.tar.xz
bind9-3b9b6d0b8e7f798023c9d109c490449d528fde80.zip
Adding upstream version 1:9.18.19.upstream/1%9.18.19upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'bin/tests/system/conf.sh.common')
-rw-r--r--bin/tests/system/conf.sh.common738
1 files changed, 738 insertions, 0 deletions
diff --git a/bin/tests/system/conf.sh.common b/bin/tests/system/conf.sh.common
new file mode 100644
index 0000000..90059dd
--- /dev/null
+++ b/bin/tests/system/conf.sh.common
@@ -0,0 +1,738 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+testsock6() {
+ if test -n "$PERL" && $PERL -e "use IO::Socket::INET6;" 2> /dev/null
+ then
+ $PERL "$TOP_SRCDIR/bin/tests/system/testsock6.pl" "$@"
+ else
+ false
+ fi
+}
+
+export LANG=C
+
+
+#
+# Common lists of system tests to run.
+#
+# The following tests are hard-coded to use ports 5300 and 9953. For
+# this reason, these must be run sequentially.
+#
+# Sequential tests that only run on unix/linux should be added to
+# SEQUENTIAL_UNIX in conf.sh.in
+#
+SEQUENTIAL_COMMON=""
+
+#
+# These tests can use ports assigned by the caller (other than 5300
+# and 9953). Because separate blocks of ports can be used for teach
+# test, these tests can be run in parallel.
+#
+# Parallel tests that only run on unix/linux should be added to
+# PARALLEL_UNIX in conf.sh.in;
+#
+# Note: some of the longer-running tests such as serve-stale and
+# rpzrecurse are scheduled first, in order to get more benefit from
+# parallelism.
+#
+PARALLEL_COMMON="
+rpzrecurse
+serve-stale
+dupsigs
+acl
+additional
+addzone
+allow-query
+auth
+autosign
+builtin
+cacheclean
+case
+catz
+cds
+checkconf
+checknames
+checkzone
+database
+digdelv
+dlz
+dns64
+dsdigest
+ecdsa
+eddsa
+ednscompliance
+emptyzones
+fetchlimit
+formerr
+forward
+geoip2
+glue
+idna
+include-multiplecfg
+inline
+integrity
+ixfr
+journal
+keepalive
+limits
+masterfile
+masterformat
+metadata
+mirror
+mkeys
+names
+notify
+nsec3
+nslookup
+nsupdate
+padding
+pending
+reclimit
+redirect
+resolver
+rndc
+rootkeysentinel
+rpz
+rrchecker
+rrl
+rrsetorder
+rsabigexponent
+runtime
+sfcache
+smartsign
+sortlist
+spf
+staticstub
+statistics
+statschannel
+stub
+synthfromdnssec
+tkey
+tools
+tsig
+tsiggss
+ttl
+unknown
+upforwd
+verify
+views
+wildcard
+xfer
+xferquota
+zero
+zonechecks"
+
+#
+# Set up color-coded test output
+#
+if [ ${SYSTEMTEST_FORCE_COLOR:-0} -eq 1 ] || test -t 1 && type tput > /dev/null 2>&1 && tput setaf 7 > /dev/null 2>&1 ; then
+ export COLOR_END=$(tput setaf 4) # blue
+ export COLOR_FAIL=$(tput setaf 1) # red
+ export COLOR_INFO=$(tput bold) # bold
+ export COLOR_NONE=$(tput sgr0)
+ export COLOR_PASS=$(tput setaf 2) # green
+ export COLOR_START=$(tput setaf 4) # blue
+ export COLOR_WARN=$(tput setaf 3) # yellow
+else
+ # set to empty strings so printf succeeds
+ export COLOR_END=''
+ export COLOR_FAIL=''
+ export COLOR_INFO=''
+ export COLOR_NONE=''
+ export COLOR_PASS=''
+ export COLOR_START=''
+ export COLOR_WARN=''
+fi
+
+export SYSTESTDIR="$(basename $PWD)"
+
+if type printf > /dev/null 2>&1
+then
+ echofail () {
+ printf "${COLOR_FAIL}%s${COLOR_NONE}\n" "$*"
+ }
+ echowarn () {
+ printf "${COLOR_WARN}%s${COLOR_NONE}\n" "$*"
+ }
+ echopass () {
+ printf "${COLOR_PASS}%s${COLOR_NONE}\n" "$*"
+ }
+ echoinfo () {
+ printf "${COLOR_INFO}%s${COLOR_NONE}\n" "$*"
+ }
+ echostart () {
+ printf "${COLOR_START}%s${COLOR_NONE}\n" "$*"
+ }
+ echoend () {
+ printf "${COLOR_END}%s${COLOR_NONE}\n" "$*"
+ }
+ echo_i() {
+ printf '%s\n' "$*" | while IFS= read -r __LINE ; do
+ echoinfo "I:$SYSTESTDIR:$__LINE"
+ done
+ }
+
+ echo_ic() {
+ printf '%s\n' "$*" | while IFS= read -r __LINE ; do
+ echoinfo "I:$SYSTESTDIR: $__LINE"
+ done
+ }
+
+ echo_d() {
+ printf '%s\n' "$*" | while IFS= read -r __LINE ; do
+ echoinfo "D:$SYSTESTDIR:$__LINE"
+ done
+ }
+else
+ echofail () {
+ echo "$*"
+ }
+ echowarn () {
+ echo "$*"
+ }
+ echopass () {
+ echo "$*"
+ }
+ echoinfo () {
+ echo "$*"
+ }
+ echostart () {
+ echo "$*"
+ }
+ echoend () {
+ echo "$*"
+ }
+
+ echo_i() {
+ echo "$@" | while IFS= read -r __LINE ; do
+ echoinfo "I:$SYSTESTDIR:$__LINE"
+ done
+ }
+
+ echo_ic() {
+ echo "$@" | while IFS= read -r __LINE ; do
+ echoinfo "I:$SYSTESTDIR: $__LINE"
+ done
+ }
+
+ echo_d() {
+ echo "$@" | while IFS= read -r __LINE ; do
+ echoinfo "D:$SYSTESTDIR:$__LINE"
+ done
+ }
+fi
+
+cat_i() {
+ while IFS= read -r __LINE ; do
+ echoinfo "I:$SYSTESTDIR:$__LINE"
+ done
+}
+
+cat_d() {
+ while IFS= read -r __LINE ; do
+ echoinfo "D:$SYSTESTDIR:$__LINE"
+ done
+}
+
+digcomp() {
+ { output=$($PERL $TOP_SRCDIR/bin/tests/system/digcomp.pl "$@"); result=$?; } || true
+ [ -n "$output" ] && { echo "digcomp failed:"; echo "$output"; } | cat_i
+ return $result
+}
+
+start_server() {
+ $PERL "$TOP_SRCDIR/bin/tests/system/start.pl" "$SYSTESTDIR" "$@"
+}
+
+stop_server() {
+ $PERL "$TOP_SRCDIR/bin/tests/system/stop.pl" "$SYSTESTDIR" "$@"
+}
+
+send() {
+ $PERL "$TOP_SRCDIR/bin/tests/system/send.pl" "$@"
+}
+
+#
+# Useful variables in test scripts
+#
+
+# The following script sets the following algorithm-related variables. These
+# are selected randomly at runtime from a list of supported algorithms. The
+# randomization is deterministic and remains stable for a period of time for a
+# given platform.
+#
+# Default algorithm for testing.
+# DEFAULT_ALGORITHM
+# DEFAULT_ALGORITHM_NUMBER
+# DEFAULT_BITS
+#
+# This is an alternative algorithm for test cases that require more than one
+# algorithm (for example algorithm rollover). Must be different from
+# DEFAULT_ALGORITHM.
+# ALTERNATIVE_ALGORITHM
+# ALTERNATIVE_ALGORITHM_NUMBER
+# ALTERNATIVE_BITS
+#
+# This is an algorithm that is used for tests against the "disable-algorithms"
+# configuration option. Must be different from above algorithms.
+# DISABLED_ALGORITHM
+# DISABLED_ALGORITHM_NUMBER
+# DISABLED_BITS
+#
+# There are multiple algoritms sets to choose from (see get_algorithms.py). To
+# override the default choice, set the ALGORITHM_SET env var (see mkeys system
+# test for example).
+eval "$($PYTHON "$TOP_SRCDIR/bin/tests/system/get_algorithms.py")"
+
+# Default HMAC algorithm.
+# also update common/rndc.conf and common/rndc.key when updating DEFAULT_HMAC
+export DEFAULT_HMAC=hmac-sha256
+
+#
+# Useful functions in test scripts
+#
+
+# assert_int_equal: compare two integer variables, $1 and $2
+#
+# If $1 and $2 are equal, return 0; if $1 and $2 are not equal, report
+# the error using the description of the tested variable provided in $3
+# and return 1.
+assert_int_equal() {
+ found="$1"
+ expected="$2"
+ description="$3"
+
+ if [ "${expected}" -ne "${found}" ]; then
+ echo_i "incorrect ${description}: got ${found}, expected ${expected}"
+ return 1
+ fi
+
+ return 0
+}
+
+# keyfile_to_keys_section: helper function for keyfile_to_*_keys() which
+# converts keyfile data into a key-style trust anchor configuration
+# section using the supplied parameters
+keyfile_to_keys() {
+ section_name=$1
+ key_prefix=$2
+ shift
+ shift
+ echo "$section_name {"
+ for keyname in $*; do
+ awk '!/^; /{
+ printf "\t\""$1"\" "
+ printf "'"$key_prefix "'"
+ printf $4 " " $5 " " $6 " \""
+ for (i=7; i<=NF; i++) printf $i
+ printf "\";\n"
+ }' $keyname.key
+ done
+ echo "};"
+}
+
+# keyfile_to_dskeys_section: helper function for keyfile_to_*_dskeys()
+# converts keyfile data into a DS-style trust anchor configuration
+# section using the supplied parameters
+keyfile_to_dskeys() {
+ section_name=$1
+ key_prefix=$2
+ shift
+ shift
+ echo "$section_name {"
+ for keyname in $*; do
+ $DSFROMKEY $keyname.key | \
+ awk '!/^; /{
+ printf "\t\""$1"\" "
+ printf "'"$key_prefix "'"
+ printf $4 " " $5 " " $6 " \""
+ for (i=7; i<=NF; i++) printf $i
+ printf "\";\n"
+ }'
+ done
+ echo "};"
+}
+
+# keyfile_to_trusted_keys: convert key data contained in the keyfile(s)
+# provided to a "trust-keys" section suitable for including in a
+# resolver's configuration file
+keyfile_to_trusted_keys() {
+ keyfile_to_keys "trusted-keys" "" $*
+}
+
+# keyfile_to_static_keys: convert key data contained in the keyfile(s)
+# provided to a *static-key* "trust-anchors" section suitable for including in
+# a resolver's configuration file
+keyfile_to_static_keys() {
+ keyfile_to_keys "trust-anchors" "static-key" $*
+}
+
+# keyfile_to_initial_keys: convert key data contained in the keyfile(s)
+# provided to an *initial-key* "trust-anchors" section suitable for including
+# in a resolver's configuration file
+keyfile_to_initial_keys() {
+ keyfile_to_keys "trust-anchors" "initial-key" $*
+}
+
+# keyfile_to_static_ds_keys: convert key data contained in the keyfile(s)
+# provided to a *static-ds* "trust-anchors" section suitable for including in a
+# resolver's configuration file
+keyfile_to_static_ds() {
+ keyfile_to_dskeys "trust-anchors" "static-ds" $*
+}
+
+# keyfile_to_initial_ds_keys: convert key data contained in the keyfile(s)
+# provided to an *initial-ds* "trust-anchors" section suitable for including
+# in a resolver's configuration file
+keyfile_to_initial_ds() {
+ keyfile_to_dskeys "trust-anchors" "initial-ds" $*
+}
+
+# keyfile_to_key_id: convert a key file name to a key ID
+#
+# For a given key file name (e.g. "Kexample.+013+06160") provided as $1,
+# print the key ID with leading zeros stripped ("6160" for the
+# aforementioned example).
+keyfile_to_key_id() {
+ echo "$1" | sed "s/.*+0\{0,4\}//"
+}
+
+# private_type_record: write a private type record recording the state of the
+# signing process
+#
+# For a given zone ($1), algorithm number ($2) and key file ($3), print the
+# private type record with default type value of 65534, indicating that the
+# signing process for this key is completed.
+private_type_record() {
+ _zone=$1
+ _algorithm=$2
+ _keyfile=$3
+
+ _id=$(keyfile_to_key_id "$_keyfile")
+
+ printf "%s. 0 IN TYPE65534 %s 5 %02x%04x0000\n" "$_zone" "\\#" "$_algorithm" "$_id"
+}
+
+# nextpart*() - functions for reading files incrementally
+#
+# These functions aim to facilitate looking for (or waiting for)
+# messages which may be logged more than once throughout the lifetime of
+# a given named instance by outputting just the part of the file which
+# has been appended since the last time we read it.
+#
+# Calling some of these functions causes temporary *.prev files to be
+# created that need to be cleaned up manually (usually by a given system
+# test's clean.sh script).
+#
+# Note that unlike other nextpart*() functions, nextpartread() is not
+# meant to be directly used in system tests; its sole purpose is to
+# reduce code duplication below.
+#
+# A quick usage example:
+#
+# $ echo line1 > named.log
+# $ echo line2 >> named.log
+# $ nextpart named.log
+# line1
+# line2
+# $ echo line3 >> named.log
+# $ nextpart named.log
+# line3
+# $ nextpart named.log
+# $ echo line4 >> named.log
+# $ nextpartpeek named.log
+# line4
+# $ nextpartpeek named.log
+# line4
+# $ nextpartreset named.log
+# $ nextpartpeek named.log
+# line1
+# line2
+# line3
+# line4
+# $ nextpart named.log
+# line1
+# line2
+# line3
+# line4
+# $ nextpart named.log
+# $
+
+# nextpartreset: reset the marker used by nextpart() and nextpartpeek()
+# so that it points to the start of the given file
+nextpartreset() {
+ echo "0" > $1.prev
+}
+
+# nextpartread: read everything that's been appended to a file since the
+# last time nextpart() was called and print it to stdout, print the
+# total number of lines read from that file so far to file descriptor 3
+nextpartread() {
+ [ -f $1.prev ] || nextpartreset $1
+ prev=$(cat $1.prev)
+ awk "NR > $prev "'{ print }
+ END { print NR > "/dev/stderr" }' $1 2>&3
+}
+
+# nextpart: read everything that's been appended to a file since the
+# last time nextpart() was called
+nextpart() {
+ nextpartread $1 3> $1.prev.tmp
+ mv $1.prev.tmp $1.prev
+}
+
+# nextpartpeek: read everything that's been appended to a file since the
+# last time nextpart() was called
+nextpartpeek() {
+ nextpartread $1 3> /dev/null
+}
+
+# _search_log: look for message $1 in file $2 with nextpart().
+_search_log() (
+ msg="$1"
+ file="$2"
+ nextpart "$file" | grep -F -e "$msg" > /dev/null
+)
+
+# _search_log_re: same as _search_log but the message is an grep -E regex
+_search_log_re() (
+ msg="$1"
+ file="$2"
+ nextpart "$file" | grep -E -e "$msg" > /dev/null
+)
+
+# _search_log_peek: look for message $1 in file $2 with nextpartpeek().
+_search_log_peek() (
+ msg="$1"
+ file="$2"
+ nextpartpeek "$file" | grep -F -e "$msg" > /dev/null
+)
+
+# wait_for_log: wait until message $2 in file $3 appears. Bail out after
+# $1 seconds. This needs to be used in conjunction with a prior call to
+# nextpart() or nextpartreset() on the same file to guarantee the offset is
+# set correctly. Tests using wait_for_log() are responsible for cleaning up
+# the created <file>.prev files.
+wait_for_log() (
+ timeout="$1"
+ msg="$2"
+ file="$3"
+ retry_quiet "$timeout" _search_log "$msg" "$file" && return 0
+ echo_i "exceeded time limit waiting for literal '$msg' in $file"
+ return 1
+)
+
+# wait_for_log_re: same as wait_for_log, but the message is an grep -E regex
+wait_for_log_re() (
+ timeout="$1"
+ msg="$2"
+ file="$3"
+ retry_quiet "$timeout" _search_log_re "$msg" "$file" && return 0
+ echo_i "exceeded time limit waiting for regex '$msg' in $file"
+ return 1
+)
+
+# wait_for_log_peek: similar to wait_for_log() but peeking, so the file offset
+# does not change.
+wait_for_log_peek() (
+ timeout="$1"
+ msg="$2"
+ file="$3"
+ retry_quiet "$timeout" _search_log_peek "$msg" "$file" && return 0
+ echo_i "exceeded time limit waiting for literal '$msg' in $file"
+ return 1
+)
+
+# _retry: keep running a command until it succeeds, up to $1 times, with
+# one-second intervals, optionally printing a message upon every attempt
+_retry() {
+ __retries="${1}"
+ shift
+
+ while :; do
+ if "$@"; then
+ return 0
+ fi
+ __retries=$((__retries-1))
+ if [ "${__retries}" -gt 0 ]; then
+ if [ "${__retry_quiet}" -ne 1 ]; then
+ echo_i "retrying"
+ fi
+ sleep 1
+ else
+ return 1
+ fi
+ done
+}
+
+# retry: call _retry() in verbose mode
+retry() {
+ __retry_quiet=0
+ _retry "$@"
+}
+
+# retry_quiet: call _retry() in silent mode
+retry_quiet() {
+ __retry_quiet=1
+ _retry "$@"
+}
+
+# _repeat: keep running command up to $1 times, unless it fails
+_repeat() (
+ __retries="${1}"
+ shift
+ while :; do
+ if ! "$@"; then
+ return 1
+ fi
+ __retries=$((__retries-1))
+ if [ "${__retries}" -le 0 ]; then
+ break
+ fi
+ done
+ return 0
+)
+
+_times() {
+ awk "BEGIN{ for(i = 1; i <= $1; i++) print i}";
+}
+
+rndc_reload() {
+ $RNDC -c ../common/rndc.conf -s $2 -p ${CONTROLPORT} reload $3 2>&1 | sed 's/^/'"I:$SYSTESTDIR:$1"' /'
+ # reloading single zone is synchronous, if we're reloading whole server
+ # we need to wait for reload to finish
+ if [ -z "$3" ]; then
+ for _ in $(_times 10); do
+ $RNDC -c ../common/rndc.conf -s $2 -p ${CONTROLPORT} status | grep "reload/reconfig in progress" > /dev/null || break
+ sleep 1
+ done
+ fi
+}
+
+rndc_reconfig() {
+ seconds=${3:-10}
+ $RNDC -c ../common/rndc.conf -s "$2" -p "${CONTROLPORT}" reconfig 2>&1 | sed 's/^/'"I:$SYSTESTDIR:$1"' /'
+ for _ in $(_times "$seconds"); do
+ "$RNDC" -c ../common/rndc.conf -s "$2" -p "${CONTROLPORT}" status | grep "reload/reconfig in progress" > /dev/null || break
+ sleep 1
+ done
+}
+
+# rndc_dumpdb: call "rndc dumpdb [...]" and wait until it completes
+#
+# The first argument is the name server instance to send the command to, in the
+# form of "nsX" (where "X" is the instance number), e.g. "ns5". The remaining
+# arguments, if any, are appended to the rndc command line after "dumpdb".
+#
+# Control channel configuration for the name server instance to send the
+# command to must match the contents of bin/tests/system/common/rndc.conf.
+#
+# rndc output is stored in a file called rndc.out.test${n}; the "n" variable is
+# required to be set by the calling tests.sh script.
+#
+# Return 0 if the dump completes successfully; return 1 if rndc returns an exit
+# code other than 0 or if the "; Dump complete" string does not appear in the
+# dump within 10 seconds.
+rndc_dumpdb() {
+ __ret=0
+ __dump_complete=0
+ __server="${1}"
+ __ip="10.53.0.$(echo "${__server}" | tr -c -d "0-9")"
+
+ shift
+ ${RNDC} -c ../common/rndc.conf -p "${CONTROLPORT}" -s "${__ip}" dumpdb "$@" > "rndc.out.test${n}" 2>&1 || __ret=1
+
+ for _ in 0 1 2 3 4 5 6 7 8 9
+ do
+ if grep '^; Dump complete$' "${__server}/named_dump.db" > /dev/null; then
+ mv "${__server}/named_dump.db" "${__server}/named_dump.db.test${n}"
+ __dump_complete=1
+ break
+ fi
+ sleep 1
+ done
+
+ if [ ${__dump_complete} -eq 0 ]; then
+ echo_i "timed out waiting for 'rndc dumpdb' to finish"
+ __ret=1
+ fi
+
+ return ${__ret}
+}
+
+# get_dig_xfer_stats: extract transfer statistics from dig output stored
+# in $1, converting them to a format used by some system tests.
+get_dig_xfer_stats() {
+ LOGFILE="$1"
+ sed -n "s/^;; XFR size: .*messages \([0-9][0-9]*\).*/messages=\1/p" "${LOGFILE}"
+ sed -n "s/^;; XFR size: \([0-9][0-9]*\) records.*/records=\1/p" "${LOGFILE}"
+ sed -n "s/^;; XFR size: .*bytes \([0-9][0-9]*\).*/bytes=\1/p" "${LOGFILE}"
+}
+
+# get_named_xfer_stats: from named log file $1, extract transfer
+# statistics for the last transfer for peer $2 and zone $3 (from a log
+# message which has to contain the string provided in $4), converting
+# them to a format used by some system tests.
+get_named_xfer_stats() {
+ LOGFILE="$1"
+ PEER="$(echo $2 | sed 's/\./\\./g')"
+ ZONE="$(echo $3 | sed 's/\./\\./g')"
+ MESSAGE="$4"
+ grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" | \
+ sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) messages.*/messages=\1/p" | tail -1
+ grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" | \
+ sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) records.*/records=\1/p" | tail -1
+ grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" | \
+ sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) bytes.*/bytes=\1/p" | tail -1
+}
+
+# copy_setports - Copy Configuration File and Replace Ports
+#
+# Convenience function to copy a configuration file, replacing the tokens
+# QUERYPORT, CONTROLPORT and EXTRAPORT[1-8] with the values of the equivalent
+# environment variables. (These values are set by test runner, which calls the
+# scripts invoking this function.)
+#
+# Usage:
+# copy_setports infile outfile
+#
+copy_setports() {
+ dir=$(echo "$TMPDIR" | sed 's/\//\\\//g')
+
+ sed -e "s/@TMPDIR@/${dir}/g" \
+ -e "s/@PORT@/${PORT}/g" \
+ -e "s/@TLSPORT@/${TLSPORT}/g" \
+ -e "s/@HTTPPORT@/${HTTPPORT}/g" \
+ -e "s/@HTTPSPORT@/${HTTPSPORT}/g" \
+ -e "s/@EXTRAPORT1@/${EXTRAPORT1}/g" \
+ -e "s/@EXTRAPORT2@/${EXTRAPORT2}/g" \
+ -e "s/@EXTRAPORT3@/${EXTRAPORT3}/g" \
+ -e "s/@EXTRAPORT4@/${EXTRAPORT4}/g" \
+ -e "s/@EXTRAPORT5@/${EXTRAPORT5}/g" \
+ -e "s/@EXTRAPORT6@/${EXTRAPORT6}/g" \
+ -e "s/@EXTRAPORT7@/${EXTRAPORT7}/g" \
+ -e "s/@EXTRAPORT8@/${EXTRAPORT8}/g" \
+ -e "s/@CONTROLPORT@/${CONTROLPORT}/g" \
+ -e "s/@DEFAULT_ALGORITHM@/${DEFAULT_ALGORITHM}/g" \
+ -e "s/@DEFAULT_ALGORITHM_NUMBER@/${DEFAULT_ALGORITHM_NUMBER}/g" \
+ -e "s/@DEFAULT_BITS@/${DEFAULT_BITS}/g" \
+ -e "s/@ALTERNATIVE_ALGORITHM@/${ALTERNATIVE_ALGORITHM}/g" \
+ -e "s/@ALTERNATIVE_ALGORITHM_NUMBER@/${ALTERNATIVE_ALGORITHM_NUMBER}/g" \
+ -e "s/@ALTERNATIVE_BITS@/${ALTERNATIVE_BITS}/g" \
+ -e "s/@DEFAULT_HMAC@/${DEFAULT_HMAC}/g" \
+ -e "s/@DISABLED_ALGORITHM@/${DISABLED_ALGORITHM}/g" \
+ -e "s/@DISABLED_ALGORITHM_NUMBER@/${DISABLED_ALGORITHM_NUMBER}/g" \
+ -e "s/@DISABLED_BITS@/${DISABLED_BITS}/g" \
+ $1 > $2
+}