summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/conf_mode/high-availability.py5
-rwxr-xr-xsrc/conf_mode/protocols_bgp.py43
-rwxr-xr-xsrc/etc/systemd/system-generators/vyos-generator94
-rw-r--r--src/etc/systemd/system/getty@.service.d/aftervyos.conf3
-rw-r--r--src/etc/systemd/system/serial-getty@.service.d/aftervyos.conf3
-rwxr-xr-xsrc/helpers/vyos_config_sync.py2
-rwxr-xr-xsrc/init/vyos-config16
-rwxr-xr-xsrc/init/vyos-router421
-rwxr-xr-xsrc/migration-scripts/vrrp/3-to-451
-rwxr-xr-xsrc/op_mode/pki.py29
-rw-r--r--src/systemd/vyos-router.service19
-rw-r--r--src/systemd/vyos.target3
12 files changed, 682 insertions, 7 deletions
diff --git a/src/conf_mode/high-availability.py b/src/conf_mode/high-availability.py
index e18b426b1..2b1cdbd23 100755
--- a/src/conf_mode/high-availability.py
+++ b/src/conf_mode/high-availability.py
@@ -175,6 +175,11 @@ def verify(ha):
# Virtual-server
if 'virtual_server' in ha:
for vs, vs_config in ha['virtual_server'].items():
+
+ if 'address' not in vs_config and 'fwmark' not in vs_config:
+ raise ConfigError('Either address or fwmark is required '
+ f'but not set for virtual-server "{vs}"')
+
if 'port' not in vs_config and 'fwmark' not in vs_config:
raise ConfigError(f'Port or fwmark is required but not set for virtual-server "{vs}"')
if 'port' in vs_config and 'fwmark' in vs_config:
diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py
index b23584bdb..532970735 100755
--- a/src/conf_mode/protocols_bgp.py
+++ b/src/conf_mode/protocols_bgp.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020-2022 VyOS maintainers and contributors
+# Copyright (C) 2020-2023 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
@@ -20,6 +20,7 @@ from sys import argv
from vyos.base import Warning
from vyos.config import Config
from vyos.configdict import dict_merge
+from vyos.configdict import node_changed
from vyos.configverify import verify_prefix_list
from vyos.configverify import verify_route_map
from vyos.configverify import verify_vrf
@@ -27,6 +28,7 @@ from vyos.template import is_ip
from vyos.template import is_interface
from vyos.template import render_to_string
from vyos.util import dict_search
+from vyos.util import get_interface_config
from vyos.validate import is_addr_assigned
from vyos import ConfigError
from vyos import frr
@@ -54,6 +56,20 @@ def get_config(config=None):
key_mangling=('-', '_'),
get_first_key=True,
no_tag_node_value_mangle=True)
+ # if config removed
+ interfaces_removed = node_changed(conf, base + ['interface'])
+ if interfaces_removed:
+ bgp['interface_removed'] = list(interfaces_removed)
+ # Add vrf mapping in <bgp interface ifname>
+ if 'interface' in bgp:
+ for interface in bgp['interface']:
+ tmp = get_interface_config(interface)
+ if dict_search('linkinfo.info_slave_kind', tmp) and \
+ tmp['linkinfo']['info_slave_kind'] == 'vrf':
+ if 'master' in tmp:
+ bgp['interface'][interface]['applied_vrf'] = tmp['master']
+ else:
+ bgp['interface'][interface]['applied_vrf'] = 'default'
# Assign the name of our VRF context. This MUST be done before the return
# statement below, else on deletion we will delete the default instance
@@ -231,6 +247,23 @@ def verify(bgp):
if 'system_as' not in bgp:
raise ConfigError('BGP system-as number must be defined!')
+ # Verify vrf on interface and bgp section
+ if 'interface' in bgp:
+ for interface in dict_search('interface', bgp):
+ if dict_search(f'interface.{interface}.mpls', bgp):
+ if 'forwarding' in bgp['interface'][interface]['mpls']:
+ if 'vrf' in bgp:
+ if bgp['interface'][interface]['applied_vrf'] != bgp['vrf']:
+ raise ConfigError(
+ f'Can not set mpls forwarding. Interface {interface} in different vrf')
+ else:
+ if bgp['interface'][interface]['applied_vrf'] != 'default':
+ raise ConfigError(
+ f'Can not set mpls forwarding. Interface {interface} in different vrf')
+ else:
+ raise ConfigError(
+ f'<protocols bgp interface {interface}> command should have options')
+
# Common verification for both peer-group and neighbor statements
for neighbor in ['neighbor', 'peer_group']:
# bail out early if there is no neighbor or peer-group statement
@@ -520,6 +553,14 @@ def apply(bgp):
vrf = ' vrf ' + bgp['vrf']
frr_cfg.load_configuration(bgp_daemon)
+
+ #If bgp interface config removed
+ for key in ['interface', 'interface_removed']:
+ if key not in bgp:
+ continue
+ for interface in bgp[key]:
+ frr_cfg.modify_section(f'^interface {interface}', stop_pattern='^exit', remove_stop_mark=True)
+
frr_cfg.modify_section(f'^router bgp \d+{vrf}', stop_pattern='^exit', remove_stop_mark=True)
if 'frr_bgpd_config' in bgp:
frr_cfg.add_before(frr.default_add_before, bgp['frr_bgpd_config'])
diff --git a/src/etc/systemd/system-generators/vyos-generator b/src/etc/systemd/system-generators/vyos-generator
new file mode 100755
index 000000000..34faab6a2
--- /dev/null
+++ b/src/etc/systemd/system-generators/vyos-generator
@@ -0,0 +1,94 @@
+#!/bin/sh
+set -f
+
+LOG=""
+DEBUG_LEVEL=1
+LOG_D="/run/vyos-router"
+ENABLE="enabled"
+DISABLE="disabled"
+FOUND="found"
+NOTFOUND="notfound"
+RUN_ENABLED_FILE="$LOG_D/$ENABLE"
+VYOS_SYSTEM_TARGET="/lib/systemd/system/vyos.target"
+VYOS_TARGET_NAME="vyos.target"
+
+debug() {
+ local lvl="$1"
+ shift
+ [ "$lvl" -gt "$DEBUG_LEVEL" ] && return
+ if [ -z "$LOG" ]; then
+ local log="$LOG_D/${0##*/}.log"
+ { [ -d "$LOG_D" ] || mkdir -p "$LOG_D"; } &&
+ { : > "$log"; } >/dev/null 2>&1 && LOG="$log" ||
+ LOG="/dev/kmsg"
+ fi
+ echo "$@" >> "$LOG"
+}
+
+default() {
+ _RET="$ENABLE"
+}
+
+main() {
+ local normal_d="$1" early_d="$2" late_d="$3"
+ local target_name="multi-user.target" gen_d="$early_d"
+ local link_path="$gen_d/${target_name}.wants/${VYOS_TARGET_NAME}"
+ local ds="$NOTFOUND"
+
+ debug 1 "$0 normal=$normal_d early=$early_d late=$late_d"
+ debug 2 "$0 $*"
+
+ local search result="error" ret=""
+ for search in default; do
+ if $search; then
+ debug 1 "$search found $_RET"
+ [ "$_RET" = "$ENABLE" -o "$_RET" = "$DISABLE" ] &&
+ result=$_RET && break
+ else
+ ret=$?
+ debug 0 "search $search returned $ret"
+ fi
+ done
+
+ # enable AND ds=found == enable
+ # enable AND ds=notfound == disable
+ # disable || <any> == disabled
+ if [ "$result" = "$ENABLE" ]; then
+ if [ -e "$link_path" ]; then
+ debug 1 "already enabled: no change needed"
+ else
+ [ -d "${link_path%/*}" ] || mkdir -p "${link_path%/*}" ||
+ debug 0 "failed to make dir $link_path"
+ if ln -snf "$VYOS_SYSTEM_TARGET" "$link_path"; then
+ debug 1 "enabled via $link_path -> $VYOS_SYSTEM_TARGET"
+ else
+ ret=$?
+ debug 0 "[$ret] enable failed:" \
+ "ln $VYOS_SYSTEM_TARGET $link_path"
+ fi
+ fi
+ : > "$RUN_ENABLED_FILE"
+ elif [ "$result" = "$DISABLE" ]; then
+ if [ -f "$link_path" ]; then
+ if rm -f "$link_path"; then
+ debug 1 "disabled. removed existing $link_path"
+ else
+ ret=$?
+ debug 0 "[$ret] disable failed, remove $link_path"
+ fi
+ else
+ debug 1 "already disabled: no change needed [no $link_path]"
+ fi
+ if [ -e "$RUN_ENABLED_FILE" ]; then
+ rm -f "$RUN_ENABLED_FILE"
+ fi
+ else
+ debug 0 "unexpected result '$result' 'ds=$ds'"
+ ret=3
+ fi
+ return $ret
+}
+
+main "$@"
+
+# vi: ts=4 expandtab
diff --git a/src/etc/systemd/system/getty@.service.d/aftervyos.conf b/src/etc/systemd/system/getty@.service.d/aftervyos.conf
new file mode 100644
index 000000000..c5753900e
--- /dev/null
+++ b/src/etc/systemd/system/getty@.service.d/aftervyos.conf
@@ -0,0 +1,3 @@
+[Service]
+ExecStartPre=-/usr/libexec/vyos/init/vyos-config
+StandardOutput=journal+console
diff --git a/src/etc/systemd/system/serial-getty@.service.d/aftervyos.conf b/src/etc/systemd/system/serial-getty@.service.d/aftervyos.conf
new file mode 100644
index 000000000..8ba42778d
--- /dev/null
+++ b/src/etc/systemd/system/serial-getty@.service.d/aftervyos.conf
@@ -0,0 +1,3 @@
+[Service]
+ExecStartPre=-/usr/libexec/vyos/init/vyos-config SERIAL
+StandardOutput=journal+console
diff --git a/src/helpers/vyos_config_sync.py b/src/helpers/vyos_config_sync.py
index 6e66a6be0..7cfa8fe88 100755
--- a/src/helpers/vyos_config_sync.py
+++ b/src/helpers/vyos_config_sync.py
@@ -24,6 +24,7 @@ import logging
from typing import Optional, List, Union, Dict, Any
from vyos.config import Config
+from vyos.template import bracketize_ipv6
CONFIG_FILE = '/run/config_sync_conf.conf'
@@ -175,6 +176,7 @@ if __name__ == '__main__':
mode = config.get('mode')
secondary_address = config.get('secondary', {}).get('address')
+ secondary_address = bracketize_ipv6(secondary_address)
secondary_key = config.get('secondary', {}).get('key')
sections = config.get('section')
timeout = int(config.get('secondary', {}).get('timeout'))
diff --git a/src/init/vyos-config b/src/init/vyos-config
new file mode 100755
index 000000000..356427024
--- /dev/null
+++ b/src/init/vyos-config
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+while [ ! -f /tmp/vyos-config-status ]
+do
+ sleep 1
+done
+
+status=$(cat /tmp/vyos-config-status)
+
+if [ -z "$1" ]; then
+ if [ $status -ne 0 ]; then
+ echo "Configuration error"
+ else
+ echo "Configuration success"
+ fi
+fi
diff --git a/src/init/vyos-router b/src/init/vyos-router
new file mode 100755
index 000000000..7b752b84b
--- /dev/null
+++ b/src/init/vyos-router
@@ -0,0 +1,421 @@
+#!/bin/bash
+# Copyright (C) 2021 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
+
+# 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
+}
+
+# if necessary, provide initial config
+init_bootfile () {
+ if [ ! -r $BOOTFILE ] ; then
+ if [ -f $vyatta_sysconfdir/config.boot.default ]; then
+ cp $vyatta_sysconfdir/config.boot.default $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
+}
+
+# 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
+ )
+}
+
+# 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
+}
+
+# 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 commits hooks from vyatta-cfg
+ excluded="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 PAM back to virgin state (no radius/tacacs services)
+ pam-auth-update --package --remove radius
+ rm -f /etc/pam_radius_auth.conf
+ pam-auth-update --package --remove tacplus
+ rm -f /etc/tacplus_nss.conf /etc/tacplus_servers
+
+ # 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
+ nft -f /usr/share/vyos/vyos-firewall-init.conf || log_failure_msg "could not initiate firewall rules"
+
+ rm -f /etc/hostname
+ ${vyos_conf_scripts_dir}/host_name.py || log_failure_msg "could not reset host-name"
+ systemctl start frr.service
+
+ # 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.py || log_failure_msg "could not reset system login"
+ ${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}/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
+ 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 $?
+
+ disabled bootfile || init_bootfile
+
+ cleanup_post_commit_hooks
+
+ log_daemon_msg "Starting VyOS router"
+ disabled migrate || migrate_bootfile
+
+ run_preconfig_script
+
+ run_postupgrade_script
+
+ update_interface_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 /
+
+ run_postconfig_scripts
+}
+
+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
+}
+
+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:
diff --git a/src/migration-scripts/vrrp/3-to-4 b/src/migration-scripts/vrrp/3-to-4
new file mode 100755
index 000000000..b0a6975c2
--- /dev/null
+++ b/src/migration-scripts/vrrp/3-to-4
@@ -0,0 +1,51 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2023 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/>.
+
+from sys import argv
+from vyos.configtree import ConfigTree
+
+if (len(argv) < 1):
+ print('Must specify file name!')
+ exit(1)
+
+file_name = argv[1]
+
+with open(file_name, 'r') as f:
+ config_file = f.read()
+
+base = ['high-availability', 'virtual-server']
+config = ConfigTree(config_file)
+
+if not config.exists(base):
+ # Nothing to do
+ exit(0)
+
+if config.exists(base):
+ for vs in config.list_nodes(base):
+ vs_base = base + [vs]
+
+ # If the fwmark is used, the address is not required
+ if not config.exists(vs_base + ['fwmark']):
+ # add option: 'virtual-server <tag> address x.x.x.x'
+ config.set(vs_base + ['address'], value=vs)
+
+
+try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+except OSError as e:
+ print(f'Failed to save the modified config: {e}')
+ exit(1)
diff --git a/src/op_mode/pki.py b/src/op_mode/pki.py
index b054690b0..7ea295ff1 100755
--- a/src/op_mode/pki.py
+++ b/src/op_mode/pki.py
@@ -840,7 +840,7 @@ def import_openvpn_secret(name, path):
install_openvpn_key(name, key_data, key_version)
# Show functions
-def show_certificate_authority(name=None):
+def show_certificate_authority(name=None, pem=False):
headers = ['Name', 'Subject', 'Issuer CN', 'Issued', 'Expiry', 'Private Key', 'Parent']
data = []
certs = get_config_ca_certificate()
@@ -852,6 +852,11 @@ def show_certificate_authority(name=None):
continue
cert = load_certificate(cert_dict['certificate'])
+
+ if name and pem:
+ print(encode_certificate(cert))
+ return
+
parent_ca_name = get_certificate_ca(cert, certs)
cert_issuer_cn = cert.issuer.rfc4514_string().split(",")[0]
@@ -867,7 +872,7 @@ def show_certificate_authority(name=None):
print("Certificate Authorities:")
print(tabulate.tabulate(data, headers))
-def show_certificate(name=None):
+def show_certificate(name=None, pem=False):
headers = ['Name', 'Type', 'Subject CN', 'Issuer CN', 'Issued', 'Expiry', 'Revoked', 'Private Key', 'CA Present']
data = []
certs = get_config_certificate()
@@ -885,6 +890,10 @@ def show_certificate(name=None):
if not cert:
continue
+ if name and pem:
+ print(encode_certificate(cert))
+ return
+
ca_name = get_certificate_ca(cert, ca_certs)
cert_subject_cn = cert.subject.rfc4514_string().split(",")[0]
cert_issuer_cn = cert.issuer.rfc4514_string().split(",")[0]
@@ -906,7 +915,7 @@ def show_certificate(name=None):
print("Certificates:")
print(tabulate.tabulate(data, headers))
-def show_crl(name=None):
+def show_crl(name=None, pem=False):
headers = ['CA Name', 'Updated', 'Revokes']
data = []
certs = get_config_ca_certificate()
@@ -927,9 +936,16 @@ def show_crl(name=None):
if not crl:
continue
+ if name and pem:
+ print(encode_certificate(crl))
+ continue
+
certs = get_revoked_by_serial_numbers([revoked.serial_number for revoked in crl])
data.append([cert_name, crl.last_update, ", ".join(certs)])
+ if name and pem:
+ return
+
print("Certificate Revocation Lists:")
print(tabulate.tabulate(data, headers))
@@ -943,6 +959,7 @@ if __name__ == '__main__':
parser.add_argument('--crl', help='Certificate Revocation List', required=False)
parser.add_argument('--sign', help='Sign certificate with specified CA', required=False)
parser.add_argument('--self-sign', help='Self-sign the certificate', action='store_true')
+ parser.add_argument('--pem', help='Output using PEM encoding', action='store_true')
# SSH
parser.add_argument('--ssh', help='SSH Key', required=False)
@@ -1032,16 +1049,16 @@ if __name__ == '__main__':
if not conf.exists(['pki', 'ca', ca_name]):
print(f'CA "{ca_name}" does not exist!')
exit(1)
- show_certificate_authority(ca_name)
+ show_certificate_authority(ca_name, args.pem)
elif args.certificate:
cert_name = None if args.certificate == 'all' else args.certificate
if cert_name:
if not conf.exists(['pki', 'certificate', cert_name]):
print(f'Certificate "{cert_name}" does not exist!')
exit(1)
- show_certificate(None if args.certificate == 'all' else args.certificate)
+ show_certificate(None if args.certificate == 'all' else args.certificate, args.pem)
elif args.crl:
- show_crl(None if args.crl == 'all' else args.crl)
+ show_crl(None if args.crl == 'all' else args.crl, args.pem)
else:
show_certificate_authority()
show_certificate()
diff --git a/src/systemd/vyos-router.service b/src/systemd/vyos-router.service
new file mode 100644
index 000000000..6f683cebb
--- /dev/null
+++ b/src/systemd/vyos-router.service
@@ -0,0 +1,19 @@
+[Unit]
+Description=VyOS Router
+After=systemd-journald-dev-log.socket time-sync.target local-fs.target cloud-config.service
+Requires=frr.service
+Conflicts=shutdown.target
+Before=systemd-user-sessions.service
+
+[Service]
+Type=simple
+Restart=no
+TimeoutSec=20min
+KillMode=process
+RemainAfterExit=yes
+ExecStart=/usr/libexec/vyos/init/vyos-router start
+ExecStop=/usr/libexec/vyos/init/vyos-router stop
+StandardOutput=journal+console
+
+[Install]
+WantedBy=vyos.target
diff --git a/src/systemd/vyos.target b/src/systemd/vyos.target
new file mode 100644
index 000000000..47c91c1cc
--- /dev/null
+++ b/src/systemd/vyos.target
@@ -0,0 +1,3 @@
+[Unit]
+Description=VyOS target
+After=multi-user.target