diff --git a/debian/rules b/debian/rules index d007089a4..9da40465f 100755 --- a/debian/rules +++ b/debian/rules @@ -1,134 +1,139 @@ #!/usr/bin/make -f DIR := debian/tmp VYOS_SBIN_DIR := usr/sbin VYOS_BIN_DIR := usr/bin VYOS_LIBEXEC_DIR := usr/libexec/vyos VYOS_DATA_DIR := usr/share/vyos VYOS_CFG_TMPL_DIR := opt/vyatta/share/vyatta-cfg/templates VYOS_OP_TMPL_DIR := opt/vyatta/share/vyatta-op/templates VYOS_MIBS_DIR := usr/share/snmp/mibs VYOS_LOCALUI_DIR := srv/localui MIGRATION_SCRIPTS_DIR := opt/vyatta/etc/config-migrate/migrate +ACTIVATION_SCRIPTS_DIR := usr/libexec/vyos/activate SYSTEM_SCRIPTS_DIR := usr/libexec/vyos/system SERVICES_DIR := usr/libexec/vyos/services DEB_TARGET_ARCH := $(shell dpkg-architecture -qDEB_TARGET_ARCH) %: dh $@ --with python3, --with quilt # Skip dh_strip_nondeterminism - this is very time consuming # and we have no non deterministic output (yet) override_dh_strip_nondeterminism: override_dh_gencontrol: dh_gencontrol -- -v$(shell (git describe --tags --long --match 'vyos/*' --match '1.4.*' --dirty 2>/dev/null || echo 0.0-no.git.tag) | sed -E 's%vyos/%%' | sed -E 's%-dirty%+dirty%') override_dh_auto_build: make all override_dh_auto_install: dh_auto_install cd python; python3 setup.py install --install-layout=deb --root ../$(DIR); cd .. # Install scripts mkdir -p $(DIR)/$(VYOS_SBIN_DIR) mkdir -p $(DIR)/$(VYOS_BIN_DIR) cp -r src/utils/* $(DIR)/$(VYOS_BIN_DIR) cp src/shim/vyshim $(DIR)/$(VYOS_SBIN_DIR) # Install conf mode scripts mkdir -p $(DIR)/$(VYOS_LIBEXEC_DIR)/conf_mode cp -r src/conf_mode/* $(DIR)/$(VYOS_LIBEXEC_DIR)/conf_mode # Install op mode scripts mkdir -p $(DIR)/$(VYOS_LIBEXEC_DIR)/op_mode cp -r src/op_mode/* $(DIR)/$(VYOS_LIBEXEC_DIR)/op_mode # Install op mode scripts mkdir -p $(DIR)/$(VYOS_LIBEXEC_DIR)/init cp -r src/init/* $(DIR)/$(VYOS_LIBEXEC_DIR)/init # Install validators mkdir -p $(DIR)/$(VYOS_LIBEXEC_DIR)/validators cp -r src/validators/* $(DIR)/$(VYOS_LIBEXEC_DIR)/validators # Install completion helpers mkdir -p $(DIR)/$(VYOS_LIBEXEC_DIR)/completion cp -r src/completion/* $(DIR)/$(VYOS_LIBEXEC_DIR)/completion # Install helper scripts cp -r src/helpers/* $(DIR)/$(VYOS_LIBEXEC_DIR)/ # Install migration scripts mkdir -p $(DIR)/$(MIGRATION_SCRIPTS_DIR) cp -r src/migration-scripts/* $(DIR)/$(MIGRATION_SCRIPTS_DIR) + # Install activation scripts + mkdir -p $(DIR)/$(ACTIVATION_SCRIPTS_DIR) + cp -r src/activation-scripts/* $(DIR)/$(ACTIVATION_SCRIPTS_DIR) + # Install system scripts mkdir -p $(DIR)/$(SYSTEM_SCRIPTS_DIR) cp -r src/system/* $(DIR)/$(SYSTEM_SCRIPTS_DIR) # Install system services mkdir -p $(DIR)/$(SERVICES_DIR) cp -r src/services/* $(DIR)/$(SERVICES_DIR) # Install configuration command definitions mkdir -p $(DIR)/$(VYOS_CFG_TMPL_DIR) cp -r templates-cfg/* $(DIR)/$(VYOS_CFG_TMPL_DIR) # Install operational command definitions mkdir -p $(DIR)/$(VYOS_OP_TMPL_DIR) cp -r templates-op/* $(DIR)/$(VYOS_OP_TMPL_DIR) # Install data files mkdir -p $(DIR)/$(VYOS_DATA_DIR) cp -r data/* $(DIR)/$(VYOS_DATA_DIR) # Create localui dir mkdir -p $(DIR)/$(VYOS_LOCALUI_DIR) # Install SNMP MIBs mkdir -p $(DIR)/$(VYOS_MIBS_DIR) cp -d mibs/* $(DIR)/$(VYOS_MIBS_DIR) # Install etc configuration files mkdir -p $(DIR)/etc cp -r src/etc/* $(DIR)/etc # Install PAM configuration snippets mkdir -p $(DIR)/usr/share/pam-configs cp -r src/pam-configs/* $(DIR)/usr/share/pam-configs # Install systemd service units mkdir -p $(DIR)/lib/systemd/system cp -r src/systemd/* $(DIR)/lib/systemd/system # Make directory for generated configuration file mkdir -p $(DIR)/etc/vyos # Install smoke test scripts mkdir -p $(DIR)/$(VYOS_LIBEXEC_DIR)/tests/smoke/ cp -r smoketest/scripts/* $(DIR)/$(VYOS_LIBEXEC_DIR)/tests/smoke # Install smoke test configs mkdir -p $(DIR)/$(VYOS_LIBEXEC_DIR)/tests/config/ cp -r smoketest/configs/* $(DIR)/$(VYOS_LIBEXEC_DIR)/tests/config # Install smoke test config tests mkdir -p $(DIR)/$(VYOS_LIBEXEC_DIR)/tests/config-tests/ cp -r smoketest/config-tests/* $(DIR)/$(VYOS_LIBEXEC_DIR)/tests/config-tests # Install system programs mkdir -p $(DIR)/$(VYOS_BIN_DIR) cp -r smoketest/bin/* $(DIR)/$(VYOS_BIN_DIR) # Install udev script mkdir -p $(DIR)/usr/lib/udev cp src/helpers/vyos_net_name $(DIR)/usr/lib/udev override_dh_installsystemd: dh_installsystemd -pvyos-1x --name vyos-router vyos-router.service dh_installsystemd -pvyos-1x --name vyos vyos.target diff --git a/debian/vyos-1x.install b/debian/vyos-1x.install index 9e43669be..b3978d38a 100644 --- a/debian/vyos-1x.install +++ b/debian/vyos-1x.install @@ -1,40 +1,41 @@ etc/commit etc/dhcp etc/ipsec.d etc/logrotate.d etc/netplug etc/opennhrp etc/modprobe.d etc/ppp etc/rsyslog.conf etc/securetty etc/security etc/skel etc/sudoers.d etc/systemd etc/sysctl.d etc/telegraf etc/udev etc/update-motd.d etc/vyos lib/ opt/ srv/localui usr/sbin usr/bin/config-mgmt usr/bin/initial-setup usr/bin/vyos-config-file-query usr/bin/vyos-config-to-commands usr/bin/vyos-config-to-json usr/bin/vyos-hostsd-client usr/lib +usr/libexec/vyos/activate usr/libexec/vyos/completion usr/libexec/vyos/conf_mode usr/libexec/vyos/init usr/libexec/vyos/op_mode usr/libexec/vyos/services usr/libexec/vyos/system usr/libexec/vyos/validators usr/libexec/vyos/*.py usr/libexec/vyos/*.sh usr/share diff --git a/python/vyos/defaults.py b/python/vyos/defaults.py index 7b0f7d9d9..e7cd69a8b 100644 --- a/python/vyos/defaults.py +++ b/python/vyos/defaults.py @@ -1,50 +1,51 @@ # Copyright 2018-2023 VyOS maintainers and contributors <maintainers@vyos.io> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see <http://www.gnu.org/licenses/>. import os base_dir = '/usr/libexec/vyos/' directories = { 'base' : base_dir, 'data' : '/usr/share/vyos/', 'conf_mode' : f'{base_dir}/conf_mode', 'op_mode' : f'{base_dir}/op_mode', 'services' : f'{base_dir}/services', 'config' : '/opt/vyatta/etc/config', 'migrate' : '/opt/vyatta/etc/config-migrate/migrate', + 'activate' : f'{base_dir}/activate', 'log' : '/var/log/vyatta', 'templates' : '/usr/share/vyos/templates/', 'certbot' : '/config/auth/letsencrypt', 'api_schema': f'{base_dir}/services/api/graphql/graphql/schema/', 'api_client_op': f'{base_dir}/services/api/graphql/graphql/client_op/', 'api_templates': f'{base_dir}/services/api/graphql/session/templates/', 'vyos_udev_dir' : '/run/udev/vyos', 'isc_dhclient_dir' : '/run/dhclient', 'dhcp6_client_dir' : '/run/dhcp6c', } config_status = '/tmp/vyos-config-status' api_config_state = '/run/http-api-state' cfg_group = 'vyattacfg' cfg_vintage = 'vyos' commit_lock = '/opt/vyatta/config/.lock' component_version_json = os.path.join(directories['data'], 'component-versions.json') config_default = os.path.join(directories['data'], 'config.boot.default') diff --git a/src/activation-scripts/20-ethernet_offload.py b/src/activation-scripts/20-ethernet_offload.py new file mode 100755 index 000000000..33b0ea469 --- /dev/null +++ b/src/activation-scripts/20-ethernet_offload.py @@ -0,0 +1,103 @@ +# Copyright 2021-2024 VyOS maintainers and contributors <maintainers@vyos.io> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library. If not, see <http://www.gnu.org/licenses/>. + +# T3619: mirror Linux Kernel defaults for ethernet offloading options into VyOS +# CLI. See https://vyos.dev/T3619#102254 for all the details. +# T3787: Remove deprecated UDP fragmentation offloading option +# T6006: add to activation-scripts: migration-scripts/interfaces/20-to-21 + +from vyos.ethtool import Ethtool +from vyos.configtree import ConfigTree + +def activate(config: ConfigTree): + base = ['interfaces', 'ethernet'] + + if not config.exists(base): + return + + for ifname in config.list_nodes(base): + eth = Ethtool(ifname) + + # If GRO is enabled by the Kernel - we reflect this on the CLI. If GRO is + # enabled via CLI but not supported by the NIC - we remove it from the CLI + configured = config.exists(base + [ifname, 'offload', 'gro']) + enabled, fixed = eth.get_generic_receive_offload() + if configured and fixed: + config.delete(base + [ifname, 'offload', 'gro']) + elif enabled and not fixed: + config.set(base + [ifname, 'offload', 'gro']) + + # If GSO is enabled by the Kernel - we reflect this on the CLI. If GSO is + # enabled via CLI but not supported by the NIC - we remove it from the CLI + configured = config.exists(base + [ifname, 'offload', 'gso']) + enabled, fixed = eth.get_generic_segmentation_offload() + if configured and fixed: + config.delete(base + [ifname, 'offload', 'gso']) + elif enabled and not fixed: + config.set(base + [ifname, 'offload', 'gso']) + + # If LRO is enabled by the Kernel - we reflect this on the CLI. If LRO is + # enabled via CLI but not supported by the NIC - we remove it from the CLI + configured = config.exists(base + [ifname, 'offload', 'lro']) + enabled, fixed = eth.get_large_receive_offload() + if configured and fixed: + config.delete(base + [ifname, 'offload', 'lro']) + elif enabled and not fixed: + config.set(base + [ifname, 'offload', 'lro']) + + # If SG is enabled by the Kernel - we reflect this on the CLI. If SG is + # enabled via CLI but not supported by the NIC - we remove it from the CLI + configured = config.exists(base + [ifname, 'offload', 'sg']) + enabled, fixed = eth.get_scatter_gather() + if configured and fixed: + config.delete(base + [ifname, 'offload', 'sg']) + elif enabled and not fixed: + config.set(base + [ifname, 'offload', 'sg']) + + # If TSO is enabled by the Kernel - we reflect this on the CLI. If TSO is + # enabled via CLI but not supported by the NIC - we remove it from the CLI + configured = config.exists(base + [ifname, 'offload', 'tso']) + enabled, fixed = eth.get_tcp_segmentation_offload() + if configured and fixed: + config.delete(base + [ifname, 'offload', 'tso']) + elif enabled and not fixed: + config.set(base + [ifname, 'offload', 'tso']) + + # Remove deprecated UDP fragmentation offloading option + if config.exists(base + [ifname, 'offload', 'ufo']): + config.delete(base + [ifname, 'offload', 'ufo']) + + # Also while processing the interface configuration, not all adapters support + # changing the speed and duplex settings. If the desired speed and duplex + # values do not work for the NIC driver, we change them back to the default + # value of "auto" - which will be applied if the CLI node is deleted. + speed_path = base + [ifname, 'speed'] + duplex_path = base + [ifname, 'duplex'] + # speed and duplex must always be set at the same time if not set to "auto" + if config.exists(speed_path) and config.exists(duplex_path): + speed = config.return_value(speed_path) + duplex = config.return_value(duplex_path) + if speed != 'auto' and duplex != 'auto': + if not eth.check_speed_duplex(speed, duplex): + config.delete(speed_path) + config.delete(duplex_path) + + # Also while processing the interface configuration, not all adapters support + # changing disabling flow-control - or change this setting. If disabling + # flow-control is not supported by the NIC, we remove the setting from CLI + flow_control_path = base + [ifname, 'disable-flow-control'] + if config.exists(flow_control_path): + if not eth.check_flow_control(): + config.delete(flow_control_path) diff --git a/src/helpers/run-config-activation.py b/src/helpers/run-config-activation.py new file mode 100755 index 000000000..58293702a --- /dev/null +++ b/src/helpers/run-config-activation.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2024 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import re +import logging +from pathlib import Path +from argparse import ArgumentParser + +from vyos.compose_config import ComposeConfig +from vyos.compose_config import ComposeConfigError +from vyos.defaults import directories + +parser = ArgumentParser() +parser.add_argument('config_file', type=str, + help="configuration file to modify with system-specific settings") +parser.add_argument('--test-script', type=str, + help="test effect of named script") + +args = parser.parse_args() + +checkpoint_file = '/run/vyos-activate-checkpoint' +log_file = Path(directories['config']).joinpath('vyos-activate.log') + +logger = logging.getLogger(__name__) +fh = logging.FileHandler(log_file) +formatter = logging.Formatter('%(message)s') +fh.setFormatter(formatter) +logger.addHandler(fh) + +if 'vyos-activate-debug' in Path('/proc/cmdline').read_text(): + print(f'\nactivate-debug enabled: file {checkpoint_file}_* on error') + debug = checkpoint_file + logger.setLevel(logging.DEBUG) +else: + debug = None + logger.setLevel(logging.INFO) + +def sort_key(s: Path): + s = s.stem + pre, rem = re.match(r'(\d*)(?:-)?(.+)', s).groups() + return int(pre or 0), rem + +def file_ext(file_name: str) -> str: + """Return an identifier from file name for checkpoint file extension. + """ + return Path(file_name).stem + +script_dir = Path(directories['activate']) + +if args.test_script: + script_list = [script_dir.joinpath(args.test_script)] +else: + script_list = sorted(script_dir.glob('*.py'), key=sort_key) + +config_file = args.config_file +config_str = Path(config_file).read_text() + +compose = ComposeConfig(config_str, checkpoint_file=debug) + +for file in script_list: + file = file.as_posix() + logger.info(f'calling {file}') + try: + compose.apply_file(file, func_name='activate') + except ComposeConfigError as e: + if debug: + compose.write(f'{compose.checkpoint_file}_{file_ext(file)}') + logger.error(f'config-activation error in {file}: {e}') + +compose.write(config_file, with_version=True) diff --git a/src/init/vyos-router b/src/init/vyos-router index a88810f08..59004fdc1 100755 --- a/src/init/vyos-router +++ b/src/init/vyos-router @@ -1,564 +1,575 @@ #!/bin/bash # Copyright (C) 2021-2024 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. . /lib/lsb/init-functions : ${vyatta_env:=/etc/default/vyatta} source $vyatta_env declare progname=${0##*/} declare action=$1; shift declare -x BOOTFILE=$vyatta_sysconfdir/config/config.boot declare -x DEFAULT_BOOTFILE=$vyatta_sysconfdir/config.boot.default # If vyos-config= boot option is present, use that file instead for x in $(cat /proc/cmdline); do [[ $x = vyos-config=* ]] || continue VYOS_CONFIG="${x#vyos-config=}" done if [ ! -z "$VYOS_CONFIG" ]; then if [ -r "$VYOS_CONFIG" ]; then echo "Config selected manually: $VYOS_CONFIG" declare -x BOOTFILE="$VYOS_CONFIG" else echo "WARNING: Could not read selected config file, using default!" fi fi declare -a subinit declare -a all_subinits=( firewall ) if [ $# -gt 0 ] ; then for s in $@ ; do [ -x ${vyatta_sbindir}/${s}.init ] && subinit[${#subinit}]=$s done else for s in ${all_subinits[@]} ; do [ -x ${vyatta_sbindir}/${s}.init ] && subinit[${#subinit}]=$s done fi GROUP=vyattacfg # easy way to make empty file without any command empty() { >$1 } # check if bootup of this portion is disabled disabled () { grep -q -w no-vyos-$1 /proc/cmdline } # Load encrypted config volume mount_encrypted_config() { persist_path=$(/opt/vyatta/sbin/vyos-persistpath) if [ $? == 0 ]; then if [ -e $persist_path/boot ]; then image_name=$(cat /proc/cmdline | sed -e s+^.*vyos-union=/boot/++ | sed -e 's/ .*$//') if [ -z "$image_name" ]; then return fi if [ ! -f $persist_path/luks/$image_name ]; then return fi vyos_tpm_key=$(python3 -c 'from vyos.tpm import read_tpm_key; print(read_tpm_key().decode())' 2>/dev/null) if [ $? -ne 0 ]; then echo "ERROR: Failed to fetch encryption key from TPM. Encrypted config volume has not been mounted" echo "Use 'encryption load' to load volume with recovery key" echo "or 'encryption disable' to decrypt volume with recovery key" return fi echo $vyos_tpm_key | tr -d '\r\n' | cryptsetup open $persist_path/luks/$image_name vyos_config --key-file=- if [ $? -ne 0 ]; then echo "ERROR: Failed to decrypt config volume. Encrypted config volume has not been mounted" echo "Use 'encryption load' to load volume with recovery key" echo "or 'encryption disable' to decrypt volume with recovery key" return fi mount /dev/mapper/vyos_config /config mount /dev/mapper/vyos_config $vyatta_sysconfdir/config echo "Mounted encrypted config volume" fi fi } unmount_encrypted_config() { persist_path=$(/opt/vyatta/sbin/vyos-persistpath) if [ $? == 0 ]; then if [ -e $persist_path/boot ]; then image_name=$(cat /proc/cmdline | sed -e s+^.*vyos-union=/boot/++ | sed -e 's/ .*$//') if [ -z "$image_name" ]; then return fi if [ ! -f $persist_path/luks/$image_name ]; then return fi umount /config umount $vyatta_sysconfdir/config cryptsetup close vyos_config fi fi } # if necessary, provide initial config init_bootfile () { # define and version default boot config if not present if [ ! -r $DEFAULT_BOOTFILE ]; then if [ -f $vyos_data_dir/config.boot.default ]; then cp $vyos_data_dir/config.boot.default $DEFAULT_BOOTFILE $vyos_libexec_dir/system-versions-foot.py >> $DEFAULT_BOOTFILE fi fi if [ ! -r $BOOTFILE ] ; then if [ -f $DEFAULT_BOOTFILE ]; then cp $DEFAULT_BOOTFILE $BOOTFILE else $vyos_libexec_dir/system-versions-foot.py > $BOOTFILE fi chgrp ${GROUP} $BOOTFILE chmod 660 $BOOTFILE fi } # if necessary, migrate initial config migrate_bootfile () { if [ -x $vyos_libexec_dir/run-config-migration.py ]; then log_progress_msg migrate sg ${GROUP} -c "$vyos_libexec_dir/run-config-migration.py $BOOTFILE" fi } +# configure system-specific settings +system_config () +{ + if [ -x $vyos_libexec_dir/run-config-activation.py ]; then + log_progress_msg system + sg ${GROUP} -c "$vyos_libexec_dir/run-config-activation.py $BOOTFILE" + fi +} + # load the initial config load_bootfile () { log_progress_msg configure ( if [ -f /etc/default/vyatta-load-boot ]; then # build-specific environment for boot-time config loading source /etc/default/vyatta-load-boot fi if [ -x $vyos_libexec_dir/vyos-boot-config-loader.py ]; then sg ${GROUP} -c "$vyos_libexec_dir/vyos-boot-config-loader.py $BOOTFILE" fi ) } # restore if missing pre-config script restore_if_missing_preconfig_script () { if [ ! -x ${vyatta_sysconfdir}/config/scripts/vyos-preconfig-bootup.script ]; then mkdir -p ${vyatta_sysconfdir}/config/scripts chgrp ${GROUP} ${vyatta_sysconfdir}/config/scripts chmod 775 ${vyatta_sysconfdir}/config/scripts cp ${vyos_rootfs_dir}/opt/vyatta/etc/config/scripts/vyos-preconfig-bootup.script ${vyatta_sysconfdir}/config/scripts/ chgrp ${GROUP} ${vyatta_sysconfdir}/config/scripts/vyos-preconfig-bootup.script chmod 750 ${vyatta_sysconfdir}/config/scripts/vyos-preconfig-bootup.script fi } # execute the pre-config script run_preconfig_script () { if [ -x $vyatta_sysconfdir/config/scripts/vyos-preconfig-bootup.script ]; then $vyatta_sysconfdir/config/scripts/vyos-preconfig-bootup.script fi } # restore if missing post-config script restore_if_missing_postconfig_script () { if [ ! -x ${vyatta_sysconfdir}/config/scripts/vyos-postconfig-bootup.script ]; then mkdir -p ${vyatta_sysconfdir}/config/scripts chgrp ${GROUP} ${vyatta_sysconfdir}/config/scripts chmod 775 ${vyatta_sysconfdir}/config/scripts cp ${vyos_rootfs_dir}/opt/vyatta/etc/config/scripts/vyos-postconfig-bootup.script ${vyatta_sysconfdir}/config/scripts/ chgrp ${GROUP} ${vyatta_sysconfdir}/config/scripts/vyos-postconfig-bootup.script chmod 750 ${vyatta_sysconfdir}/config/scripts/vyos-postconfig-bootup.script fi } # execute the post-config scripts run_postconfig_scripts () { if [ -x $vyatta_sysconfdir/config/scripts/vyatta-postconfig-bootup.script ]; then $vyatta_sysconfdir/config/scripts/vyatta-postconfig-bootup.script fi if [ -x $vyatta_sysconfdir/config/scripts/vyos-postconfig-bootup.script ]; then $vyatta_sysconfdir/config/scripts/vyos-postconfig-bootup.script fi } run_postupgrade_script () { if [ -f $vyatta_sysconfdir/config/.upgraded ]; then # Run the system script /usr/libexec/vyos/system/post-upgrade # Run user scripts if [ -d $vyatta_sysconfdir/config/scripts/post-upgrade.d ]; then run-parts $vyatta_sysconfdir/config/scripts/post-upgrade.d fi rm -f $vyatta_sysconfdir/config/.upgraded fi } # # On image booted machines, we need to mount /boot from the image-specific # boot directory so that kernel package installation will put the # files in the right place. We also have to mount /boot/grub from the # system-wide grub directory so that tools that edit the grub.cfg # file will find it in the expected location. # bind_mount_boot () { persist_path=$(/opt/vyatta/sbin/vyos-persistpath) if [ $? == 0 ]; then if [ -e $persist_path/boot ]; then image_name=$(cat /proc/cmdline | sed -e s+^.*vyos-union=/boot/++ | sed -e 's/ .*$//') if [ -n "$image_name" ]; then mount --bind $persist_path/boot/$image_name /boot if [ $? -ne 0 ]; then echo "Couldn't bind mount /boot" fi if [ ! -d /boot/grub ]; then mkdir /boot/grub fi mount --bind $persist_path/boot/grub /boot/grub if [ $? -ne 0 ]; then echo "Couldn't bind mount /boot/grub" fi fi fi fi } clear_or_override_config_files () { for conf in snmp/snmpd.conf snmp/snmptrapd.conf snmp/snmp.conf \ keepalived/keepalived.conf cron.d/vyos-crontab \ ipvsadm.rules default/ipvsadm resolv.conf do if [ -s /etc/$conf ] ; then empty /etc/$conf chmod 0644 /etc/$conf fi done } update_interface_config () { if [ -d /run/udev/vyos ]; then $vyos_libexec_dir/vyos-interface-rescan.py $BOOTFILE fi } cleanup_post_commit_hooks () { # Remove links from the post-commit hooks directory. # note that this approach only supports hooks that are "configured", # i.e., it does not support hooks that need to always be present. cpostdir=$(cli-shell-api getPostCommitHookDir) # exclude commit hooks that need to always be present excluded="00vyos-sync 10vyatta-log-commit.pl 99vyos-user-postcommit-hooks" if [ -d "$cpostdir" ]; then for f in $cpostdir/*; do if [[ ! $excluded =~ $(basename $f) ]]; then rm -f $cpostdir/$(basename $f) fi done fi } # These are all the default security setting which are later # overridden when configuration is read. These are the values the # system defaults. security_reset () { # restore NSS cofniguration back to sane system defaults # will be overwritten later when configuration is loaded cat <<EOF >/etc/nsswitch.conf passwd: files group: files shadow: files gshadow: files # Per T2678, commenting out myhostname hosts: files dns #myhostname networks: files protocols: db files services: db files ethers: db files rpc: db files netgroup: nis EOF # restore PAM back to virgin state (no radius/tacacs services) pam-auth-update --disable radius-mandatory radius-optional rm -f /etc/pam_radius_auth.conf pam-auth-update --disable tacplus-mandatory tacplus-optional rm -f /etc/tacplus_nss.conf /etc/tacplus_servers # and no Google authenticator for 2FA/MFA pam-auth-update --disable mfa-google-authenticator # Certain configuration files are re-generated by the configuration # subsystem and must reside under /etc and can not easily be moved to /run. # So on every boot we simply delete any remaining files and let the CLI # regenearte them. # PPPoE rm -f /etc/ppp/peers/pppoe* /etc/ppp/peers/wlm* # IPSec rm -rf /etc/ipsec.conf /etc/ipsec.secrets find /etc/swanctl -type f | xargs rm -f # limit cleanup rm -f /etc/security/limits.d/10-vyos.conf # iproute2 cleanup rm -f /etc/iproute2/rt_tables.d/vyos-*.conf # Container rm -f /etc/containers/storage.conf /etc/containers/registries.conf /etc/containers/containers.conf # Clean all networks and re-create them from our CLI rm -f /etc/containers/networks/* # System Options (SSH/cURL) rm -f /etc/ssh/ssh_config.d/*vyos*.conf rm -f /etc/curlrc } # XXX: T3885 - generate persistend DHCPv6 DUID (Type4 - UUID based) gen_duid () { DUID_FILE="/var/lib/dhcpv6/dhcp6c_duid" UUID_FILE="/sys/class/dmi/id/product_uuid" UUID_FILE_ALT="/sys/class/dmi/id/product_serial" if [ ! -f ${UUID_FILE} ] && [ ! -f ${UUID_FILE_ALT} ]; then return 1 fi # DUID is based on the BIOS/EFI UUID. We omit additional - characters if [ -f ${UUID_FILE} ]; then UUID=$(cat ${UUID_FILE} | tr -d -) fi if [ -z ${UUID} ]; then UUID=$(uuidgen --sha1 --namespace @dns --name $(cat ${UUID_FILE_ALT}) | tr -d -) fi # Add DUID type4 (UUID) information DUID_TYPE="0004" # The length-information (as per RFC6355 UUID is 128 bits long) is in big-endian # format - beware when porting to ARM64. The length field consists out of the # UUID (128 bit + 16 bits DUID type) resulting in hex 12. DUID_LEN="0012" if [ "$(echo -n I | od -to2 | head -n1 | cut -f2 -d" " | cut -c6 )" -eq 1 ]; then # true on little-endian (x86) systems DUID_LEN="1200" fi for i in $(echo -n ${DUID_LEN}${DUID_TYPE}${UUID} | sed 's/../& /g'); do echo -ne "\x$i" done > ${DUID_FILE} } start () { # reset and clean config files security_reset || log_failure_msg "security reset failed" # some legacy directories migrated over from old rl-system.init mkdir -p /var/run/vyatta /var/log/vyatta chgrp vyattacfg /var/run/vyatta /var/log/vyatta chmod 775 /var/run/vyatta /var/log/vyatta log_daemon_msg "Waiting for NICs to settle down" # On boot time udev migth take a long time to reorder nic's, this will ensure that # all udev activity is completed and all nics presented at boot-time will have their # final name before continuing with vyos-router initialization. SECONDS=0 udevadm settle STATUS=$? log_progress_msg "settled in ${SECONDS}sec." log_end_msg ${STATUS} # mountpoint for bpf maps required by xdp mount -t bpf none /sys/fs/bpf # Clear out Debian APT source config file empty /etc/apt/sources.list # Generate DHCPv6 DUID gen_duid || log_failure_msg "could not generate DUID" # Mount a temporary filesystem for container networks. # Configuration should be loaded from VyOS cli. cni_dir="/etc/cni/net.d" [ ! -d ${cni_dir} ] && mkdir -p ${cni_dir} mount -t tmpfs none ${cni_dir} # Init firewall nfct helper add rpc inet tcp nfct helper add rpc inet udp nfct helper add tns inet tcp nfct helper add rpc inet6 tcp nfct helper add rpc inet6 udp nfct helper add tns inet6 tcp nft --file /usr/share/vyos/vyos-firewall-init.conf || log_failure_msg "could not initiate firewall rules" # As VyOS does not execute commands that are not present in the CLI we call # the script by hand to have a single source for the login banner and MOTD ${vyos_conf_scripts_dir}/system_console.py || log_failure_msg "could not reset serial console" ${vyos_conf_scripts_dir}/system_login_banner.py || log_failure_msg "could not reset motd and issue files" ${vyos_conf_scripts_dir}/system_option.py || log_failure_msg "could not reset system option files" ${vyos_conf_scripts_dir}/system_ip.py || log_failure_msg "could not reset system IPv4 options" ${vyos_conf_scripts_dir}/system_ipv6.py || log_failure_msg "could not reset system IPv6 options" ${vyos_conf_scripts_dir}/system_conntrack.py || log_failure_msg "could not reset conntrack subsystem" ${vyos_conf_scripts_dir}/container.py || log_failure_msg "could not reset container subsystem" clear_or_override_config_files || log_failure_msg "could not reset config files" # enable some debugging before loading the configuration if grep -q vyos-debug /proc/cmdline; then log_action_begin_msg "Enable runtime debugging options" touch /tmp/vyos.container.debug touch /tmp/vyos.ifconfig.debug touch /tmp/vyos.frr.debug touch /tmp/vyos.container.debug touch /tmp/vyos.smoketest.debug fi log_action_begin_msg "Mounting VyOS Config" # ensure the vyatta_configdir supports a large number of inodes since # the config hierarchy is often inode-bound (instead of size). # impose a minimum and then scale up dynamically with the actual size # of the system memory. local tmem=$(sed -n 's/^MemTotal: \+\([0-9]\+\) kB$/\1/p' /proc/meminfo) local tpages local tmpfs_opts="nosuid,nodev,mode=775,nr_inodes=0" #automatically allocate inodes mount -o $tmpfs_opts -t tmpfs none ${vyatta_configdir} \ && chgrp ${GROUP} ${vyatta_configdir} log_action_end_msg $? mount_encrypted_config # T5239: early read of system hostname as this value is read-only once during # FRR initialisation tmp=$(${vyos_libexec_dir}/read-saved-value.py --path "system host-name") hostnamectl set-hostname --static "$tmp" ${vyos_conf_scripts_dir}/system_frr.py || log_failure_msg "could not reset FRR config" # If for any reason FRR was not started by system_frr.py - start it anyways. # This is a safety net! systemctl start frr.service disabled bootfile || init_bootfile cleanup_post_commit_hooks log_daemon_msg "Starting VyOS router" disabled migrate || migrate_bootfile restore_if_missing_preconfig_script run_preconfig_script run_postupgrade_script update_interface_config + disabled system_config || system_config + for s in ${subinit[@]} ; do if ! disabled $s; then log_progress_msg $s if ! ${vyatta_sbindir}/${s}.init start then log_failure_msg exit 1 fi fi done bind_mount_boot disabled configure || load_bootfile log_end_msg $? telinit q chmod g-w,o-w / restore_if_missing_postconfig_script run_postconfig_scripts tmp=$(${vyos_libexec_dir}/read-saved-value.py --path "protocols rpki cache") if [[ ! -z "$tmp" ]]; then vtysh -c "rpki start" fi } stop() { local -i status=0 log_daemon_msg "Stopping VyOS router" for ((i=${#sub_inits[@]} - 1; i >= 0; i--)) ; do s=${subinit[$i]} log_progress_msg $s ${vyatta_sbindir}/${s}.init stop let status\|=$? done log_end_msg $status log_action_begin_msg "Un-mounting VyOS Config" umount ${vyatta_configdir} log_action_end_msg $? systemctl stop frr.service unmount_encrypted_config } case "$action" in start) start ;; stop) stop ;; restart|force-reload) stop && start ;; *) log_failure_msg "usage: $progname [ start|stop|restart ] [ subinit ... ]" ; false ;; esac exit $? # Local Variables: # mode: shell-script # sh-indentation: 4 # End: