summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/conf_mode/firewall.py2
-rwxr-xr-xsrc/conf_mode/policy_route.py47
-rwxr-xr-xsrc/conf_mode/service_dhcp-server.py47
-rwxr-xr-xsrc/conf_mode/service_ids_ddos-protection.py104
-rwxr-xr-xsrc/conf_mode/system_host-name.py2
-rwxr-xr-xsrc/conf_mode/system_login.py10
-rwxr-xr-xsrc/conf_mode/system_option.py7
-rwxr-xr-xsrc/conf_mode/system_syslog.py2
-rw-r--r--src/etc/dhcp/dhclient-enter-hooks.d/06-vyos-nodefaultroute20
-rwxr-xr-xsrc/etc/netplug/vyos-netplug-dhcp-client38
-rw-r--r--src/etc/sysctl.d/30-vyos-router.conf10
-rw-r--r--src/etc/systemd/system/fastnetmon.service.d/override.conf12
-rw-r--r--src/etc/systemd/system/kea-ctrl-agent.service.d/override.conf10
-rw-r--r--src/etc/systemd/system/kea-dhcp-ddns-server.service.d/override.conf7
-rwxr-xr-xsrc/helpers/geoip-update.py17
-rwxr-xr-xsrc/init/vyos-router15
-rw-r--r--src/migration-scripts/dhcp-server/7-to-86
-rw-r--r--src/migration-scripts/ids/1-to-230
-rwxr-xr-xsrc/op_mode/image_installer.py49
-rwxr-xr-xsrc/services/vyos-conntrack-logger2
-rwxr-xr-xsrc/services/vyos-domain-resolver8
-rwxr-xr-xsrc/services/vyos-hostsd4
-rw-r--r--src/systemd/netplug.service9
-rw-r--r--src/systemd/vyos.target2
24 files changed, 265 insertions, 195 deletions
diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py
index cebe57092..72f2d39f4 100755
--- a/src/conf_mode/firewall.py
+++ b/src/conf_mode/firewall.py
@@ -627,7 +627,7 @@ def apply(firewall):
# Call helper script to Update set contents
if 'name' in firewall['geoip_updated'] or 'ipv6_name' in firewall['geoip_updated']:
print('Updating GeoIP. Please wait...')
- geoip_update(firewall)
+ geoip_update(firewall=firewall)
return None
diff --git a/src/conf_mode/policy_route.py b/src/conf_mode/policy_route.py
index 223175b8a..521764896 100755
--- a/src/conf_mode/policy_route.py
+++ b/src/conf_mode/policy_route.py
@@ -21,13 +21,16 @@ from sys import exit
from vyos.base import Warning
from vyos.config import Config
+from vyos.configdiff import get_config_diff, Diff
from vyos.template import render
from vyos.utils.dict import dict_search_args
+from vyos.utils.dict import dict_search_recursive
from vyos.utils.process import cmd
from vyos.utils.process import run
from vyos.utils.network import get_vrf_tableid
from vyos.defaults import rt_global_table
from vyos.defaults import rt_global_vrf
+from vyos.firewall import geoip_update
from vyos import ConfigError
from vyos import airbag
airbag.enable()
@@ -43,6 +46,43 @@ valid_groups = [
'interface_group'
]
+def geoip_updated(conf, policy):
+ diff = get_config_diff(conf)
+ node_diff = diff.get_child_nodes_diff(['policy'], expand_nodes=Diff.DELETE, recursive=True)
+
+ out = {
+ 'name': [],
+ 'ipv6_name': [],
+ 'deleted_name': [],
+ 'deleted_ipv6_name': []
+ }
+ updated = False
+
+ for key, path in dict_search_recursive(policy, 'geoip'):
+ set_name = f'GEOIP_CC_{path[0]}_{path[1]}_{path[3]}'
+ if (path[0] == 'route'):
+ out['name'].append(set_name)
+ elif (path[0] == 'route6'):
+ set_name = f'GEOIP_CC6_{path[0]}_{path[1]}_{path[3]}'
+ out['ipv6_name'].append(set_name)
+
+ updated = True
+
+ if 'delete' in node_diff:
+ for key, path in dict_search_recursive(node_diff['delete'], 'geoip'):
+ set_name = f'GEOIP_CC_{path[0]}_{path[1]}_{path[3]}'
+ if (path[0] == 'route'):
+ out['deleted_name'].append(set_name)
+ elif (path[0] == 'route6'):
+ set_name = f'GEOIP_CC6_{path[0]}_{path[1]}_{path[3]}'
+ out['deleted_ipv6_name'].append(set_name)
+ updated = True
+
+ if updated:
+ return out
+
+ return False
+
def get_config(config=None):
if config:
conf = config
@@ -60,6 +100,7 @@ def get_config(config=None):
if 'dynamic_group' in policy['firewall_group']:
del policy['firewall_group']['dynamic_group']
+ policy['geoip_updated'] = geoip_updated(conf, policy)
return policy
def verify_rule(policy, name, rule_conf, ipv6, rule_id):
@@ -203,6 +244,12 @@ def apply(policy):
apply_table_marks(policy)
+ if policy['geoip_updated']:
+ # Call helper script to Update set contents
+ if 'name' in policy['geoip_updated'] or 'ipv6_name' in policy['geoip_updated']:
+ print('Updating GeoIP. Please wait...')
+ geoip_update(policy=policy)
+
return None
if __name__ == '__main__':
diff --git a/src/conf_mode/service_dhcp-server.py b/src/conf_mode/service_dhcp-server.py
index 5a729af74..99c7e6a1f 100755
--- a/src/conf_mode/service_dhcp-server.py
+++ b/src/conf_mode/service_dhcp-server.py
@@ -41,9 +41,9 @@ from vyos import airbag
airbag.enable()
-ctrl_config_file = '/run/kea/kea-ctrl-agent.conf'
ctrl_socket = '/run/kea/dhcp4-ctrl-socket'
config_file = '/run/kea/kea-dhcp4.conf'
+config_file_d2 = '/run/kea/kea-dhcp-ddns.conf'
lease_file = '/config/dhcp/dhcp4-leases.csv'
lease_file_glob = '/config/dhcp/dhcp4-leases*'
user_group = '_kea'
@@ -171,6 +171,15 @@ def get_config(config=None):
return dhcp
+def verify_ddns_domain_servers(domain_type, domain):
+ if 'dns_server' in domain:
+ invalid_servers = []
+ for server_no, server_config in domain['dns_server'].items():
+ if 'address' not in server_config:
+ invalid_servers.append(server_no)
+ if len(invalid_servers) > 0:
+ raise ConfigError(f'{domain_type} DNS servers {", ".join(invalid_servers)} in DDNS configuration need to have an IP address')
+ return None
def verify(dhcp):
# bail out early - looks like removal from running config
@@ -423,6 +432,22 @@ def verify(dhcp):
if not interface_exists(interface):
raise ConfigError(f'listen-interface "{interface}" does not exist')
+ if 'dynamic_dns_update' in dhcp:
+ ddns = dhcp['dynamic_dns_update']
+ if 'tsig_key' in ddns:
+ invalid_keys = []
+ for tsig_key_name, tsig_key_config in ddns['tsig_key'].items():
+ if not ('algorithm' in tsig_key_config and 'secret' in tsig_key_config):
+ invalid_keys.append(tsig_key_name)
+ if len(invalid_keys) > 0:
+ raise ConfigError(f'Both algorithm and secret need to be set for TSIG keys: {", ".join(invalid_keys)}')
+
+ if 'forward_domain' in ddns:
+ verify_ddns_domain_servers('Forward', ddns['forward_domain'])
+
+ if 'reverse_domain' in ddns:
+ verify_ddns_domain_servers('Reverse', ddns['reverse_domain'])
+
return None
@@ -480,25 +505,26 @@ def generate(dhcp):
dhcp['high_availability']['ca_cert_file'] = ca_cert_file
render(
- ctrl_config_file,
- 'dhcp-server/kea-ctrl-agent.conf.j2',
- dhcp,
- user=user_group,
- group=user_group,
- )
- render(
config_file,
'dhcp-server/kea-dhcp4.conf.j2',
dhcp,
user=user_group,
group=user_group,
)
+ if 'dynamic_dns_update' in dhcp:
+ render(
+ config_file_d2,
+ 'dhcp-server/kea-dhcp-ddns.conf.j2',
+ dhcp,
+ user=user_group,
+ group=user_group
+ )
return None
def apply(dhcp):
- services = ['kea-ctrl-agent', 'kea-dhcp4-server', 'kea-dhcp-ddns-server']
+ services = ['kea-dhcp4-server', 'kea-dhcp-ddns-server']
if not dhcp or 'disable' in dhcp:
for service in services:
@@ -515,9 +541,6 @@ def apply(dhcp):
if service == 'kea-dhcp-ddns-server' and 'dynamic_dns_update' not in dhcp:
action = 'stop'
- if service == 'kea-ctrl-agent' and 'high_availability' not in dhcp:
- action = 'stop'
-
call(f'systemctl {action} {service}.service')
return None
diff --git a/src/conf_mode/service_ids_ddos-protection.py b/src/conf_mode/service_ids_ddos-protection.py
deleted file mode 100755
index 276a71fcb..000000000
--- a/src/conf_mode/service_ids_ddos-protection.py
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2018-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/>.
-
-import os
-
-from sys import exit
-
-from vyos.config import Config
-from vyos.template import render
-from vyos.utils.process import call
-from vyos import ConfigError
-from vyos import airbag
-airbag.enable()
-
-config_file = r'/run/fastnetmon/fastnetmon.conf'
-networks_list = r'/run/fastnetmon/networks_list'
-excluded_networks_list = r'/run/fastnetmon/excluded_networks_list'
-attack_dir = '/var/log/fastnetmon_attacks'
-
-def get_config(config=None):
- if config:
- conf = config
- else:
- conf = Config()
- base = ['service', 'ids', 'ddos-protection']
- if not conf.exists(base):
- return None
-
- fastnetmon = conf.get_config_dict(base, key_mangling=('-', '_'),
- get_first_key=True,
- with_recursive_defaults=True)
-
- return fastnetmon
-
-def verify(fastnetmon):
- if not fastnetmon:
- return None
-
- if 'mode' not in fastnetmon:
- raise ConfigError('Specify operating mode!')
-
- if fastnetmon.get('mode') == 'mirror' and 'listen_interface' not in fastnetmon:
- raise ConfigError("Incorrect settings for 'mode mirror': must specify interface(s) for traffic mirroring")
-
- if fastnetmon.get('mode') == 'sflow' and 'listen_address' not in fastnetmon.get('sflow', {}):
- raise ConfigError("Incorrect settings for 'mode sflow': must specify sFlow 'listen-address'")
-
- if 'alert_script' in fastnetmon:
- if os.path.isfile(fastnetmon['alert_script']):
- # Check script permissions
- if not os.access(fastnetmon['alert_script'], os.X_OK):
- raise ConfigError('Script "{alert_script}" is not executable!'.format(fastnetmon['alert_script']))
- else:
- raise ConfigError('File "{alert_script}" does not exists!'.format(fastnetmon))
-
-def generate(fastnetmon):
- if not fastnetmon:
- for file in [config_file, networks_list]:
- if os.path.isfile(file):
- os.unlink(file)
-
- return None
-
- # Create dir for log attack details
- if not os.path.exists(attack_dir):
- os.mkdir(attack_dir)
-
- render(config_file, 'ids/fastnetmon.j2', fastnetmon)
- render(networks_list, 'ids/fastnetmon_networks_list.j2', fastnetmon)
- render(excluded_networks_list, 'ids/fastnetmon_excluded_networks_list.j2', fastnetmon)
- return None
-
-def apply(fastnetmon):
- systemd_service = 'fastnetmon.service'
- if not fastnetmon:
- # Stop fastnetmon service if removed
- call(f'systemctl stop {systemd_service}')
- else:
- call(f'systemctl reload-or-restart {systemd_service}')
-
- return None
-
-if __name__ == '__main__':
- try:
- c = get_config()
- verify(c)
- generate(c)
- apply(c)
- except ConfigError as e:
- print(e)
- exit(1)
diff --git a/src/conf_mode/system_host-name.py b/src/conf_mode/system_host-name.py
index fef034d1c..de4accda2 100755
--- a/src/conf_mode/system_host-name.py
+++ b/src/conf_mode/system_host-name.py
@@ -175,7 +175,7 @@ def apply(config):
# Restart services that use the hostname
if hostname_new != hostname_old:
- tmp = systemd_services['rsyslog']
+ tmp = systemd_services['syslog']
call(f'systemctl restart {tmp}')
# If SNMP is running, restart it too
diff --git a/src/conf_mode/system_login.py b/src/conf_mode/system_login.py
index 3fed6d273..4febb6494 100755
--- a/src/conf_mode/system_login.py
+++ b/src/conf_mode/system_login.py
@@ -15,7 +15,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
-import warnings
from passlib.hosts import linux_context
from psutil import users
@@ -30,12 +29,9 @@ from vyos.config import Config
from vyos.configverify import verify_vrf
from vyos.template import render
from vyos.template import is_ipv4
-from vyos.utils.auth import (
- DEFAULT_PASSWORD,
- EPasswdStrength,
- evaluate_strength,
- get_current_user
-)
+from vyos.utils.auth import EPasswdStrength
+from vyos.utils.auth import evaluate_strength
+from vyos.utils.auth import get_current_user
from vyos.utils.configfs import delete_cli_node
from vyos.utils.configfs import add_cli_node
from vyos.utils.dict import dict_search
diff --git a/src/conf_mode/system_option.py b/src/conf_mode/system_option.py
index 064a1aa91..b45a9d8a6 100755
--- a/src/conf_mode/system_option.py
+++ b/src/conf_mode/system_option.py
@@ -122,6 +122,10 @@ def generate(options):
render(ssh_config, 'system/ssh_config.j2', options)
render(usb_autosuspend, 'system/40_usb_autosuspend.j2', options)
+ # XXX: This code path and if statements must be kept in sync with the Kernel
+ # option handling in image_installer.py:get_cli_kernel_options(). This
+ # occurance is used for having the appropriate options passed to GRUB
+ # when re-configuring options on the CLI.
cmdline_options = []
if 'kernel' in options:
if 'disable_mitigations' in options['kernel']:
@@ -131,8 +135,7 @@ def generate(options):
if 'amd_pstate_driver' in options['kernel']:
mode = options['kernel']['amd_pstate_driver']
cmdline_options.append(
- f'initcall_blacklist=acpi_cpufreq_init amd_pstate={mode}'
- )
+ f'initcall_blacklist=acpi_cpufreq_init amd_pstate={mode}')
grub_util.update_kernel_cmdline_options(' '.join(cmdline_options))
return None
diff --git a/src/conf_mode/system_syslog.py b/src/conf_mode/system_syslog.py
index 414bd4b6b..bdab09f3c 100755
--- a/src/conf_mode/system_syslog.py
+++ b/src/conf_mode/system_syslog.py
@@ -35,7 +35,7 @@ rsyslog_conf = '/run/rsyslog/rsyslog.conf'
logrotate_conf = '/etc/logrotate.d/vyos-rsyslog'
systemd_socket = 'syslog.socket'
-systemd_service = systemd_services['rsyslog']
+systemd_service = systemd_services['syslog']
def get_config(config=None):
if config:
diff --git a/src/etc/dhcp/dhclient-enter-hooks.d/06-vyos-nodefaultroute b/src/etc/dhcp/dhclient-enter-hooks.d/06-vyos-nodefaultroute
new file mode 100644
index 000000000..38f674276
--- /dev/null
+++ b/src/etc/dhcp/dhclient-enter-hooks.d/06-vyos-nodefaultroute
@@ -0,0 +1,20 @@
+# Don't add default route if no-default-route is configured for interface
+
+# As configuration is not available to cli-shell-api at the first boot, we must use vyos.config, which contains a workaround for this
+function get_no_default_route {
+python3 - <<PYEND
+from vyos.config import Config
+import os
+
+config = Config()
+if config.exists('interfaces'):
+ iface_types = config.list_nodes('interfaces')
+ for iface_type in iface_types:
+ if config.exists("interfaces {} {} dhcp-options no-default-route".format(iface_type, os.environ['interface'])):
+ print("True")
+PYEND
+}
+
+if [[ "$(get_no_default_route)" == 'True' ]]; then
+ new_routers=""
+fi
diff --git a/src/etc/netplug/vyos-netplug-dhcp-client b/src/etc/netplug/vyos-netplug-dhcp-client
index 4cc824afd..a230fe900 100755
--- a/src/etc/netplug/vyos-netplug-dhcp-client
+++ b/src/etc/netplug/vyos-netplug-dhcp-client
@@ -20,10 +20,10 @@ import sys
from time import sleep
from vyos.config import Config
-from vyos.configdict import get_interface_dict
-from vyos.ifconfig import Interface
from vyos.ifconfig import Section
from vyos.utils.boot import boot_configuration_complete
+from vyos.utils.process import cmd
+from vyos.utils.process import is_systemd_service_active
from vyos.utils.commit import commit_in_progress
from vyos import airbag
@@ -38,20 +38,34 @@ if not boot_configuration_complete():
sys.exit(1)
interface = sys.argv[1]
-# helper scripts should only work on physical interfaces not on individual
-# sub-interfaces. Moving e.g. a VLAN interface in/out a VRF will also trigger
-# this script which should be prohibited - bail out early
-if '.' in interface:
- sys.exit(0)
while commit_in_progress():
- sleep(1)
+ sleep(0.250)
in_out = sys.argv[2]
config = Config()
interface_path = ['interfaces'] + Section.get_config_path(interface).split()
-_, interface_config = get_interface_dict(
- config, interface_path[:-1], ifname=interface, with_pki=True
-)
-Interface(interface).update(interface_config)
+
+systemdV4_service = f'dhclient@{interface}.service'
+systemdV6_service = f'dhcp6c@{interface}.service'
+if in_out == 'out':
+ # Interface moved state to down
+ if is_systemd_service_active(systemdV4_service):
+ cmd(f'systemctl stop {systemdV4_service}')
+ if is_systemd_service_active(systemdV6_service):
+ cmd(f'systemctl stop {systemdV6_service}')
+elif in_out == 'in':
+ if config.exists_effective(interface_path + ['address']):
+ tmp = config.return_effective_values(interface_path + ['address'])
+ # Always (re-)start the DHCP(v6) client service. If the DHCP(v6) client
+ # is already running - which could happen if the interface is re-
+ # configured in operational down state, it will have a backoff
+ # time increasing while not receiving a DHCP(v6) reply.
+ #
+ # To make the interface instantly available, and as for a DHCP(v6) lease
+ # we will re-start the service and thus cancel the backoff time.
+ if 'dhcp' in tmp:
+ cmd(f'systemctl restart {systemdV4_service}')
+ if 'dhcpv6' in tmp:
+ cmd(f'systemctl restart {systemdV6_service}')
diff --git a/src/etc/sysctl.d/30-vyos-router.conf b/src/etc/sysctl.d/30-vyos-router.conf
index 76be41ddc..ef81cebac 100644
--- a/src/etc/sysctl.d/30-vyos-router.conf
+++ b/src/etc/sysctl.d/30-vyos-router.conf
@@ -83,6 +83,16 @@ net.ipv4.conf.default.ignore_routes_with_linkdown=1
net.ipv6.conf.all.ignore_routes_with_linkdown=1
net.ipv6.conf.default.ignore_routes_with_linkdown=1
+# Disable IPv6 interface autoconfigurationnable packet forwarding for IPv6
+net.ipv6.conf.all.autoconf=0
+net.ipv6.conf.default.autoconf=0
+net.ipv6.conf.*.autoconf=0
+
+# Disable IPv6 router advertisements
+net.ipv6.conf.all.accept_ra=0
+net.ipv6.conf.default.accept_ra=0
+net.ipv6.conf.*.accept_ra=0
+
# Enable packet forwarding for IPv6
net.ipv6.conf.all.forwarding=1
diff --git a/src/etc/systemd/system/fastnetmon.service.d/override.conf b/src/etc/systemd/system/fastnetmon.service.d/override.conf
deleted file mode 100644
index 841666070..000000000
--- a/src/etc/systemd/system/fastnetmon.service.d/override.conf
+++ /dev/null
@@ -1,12 +0,0 @@
-[Unit]
-RequiresMountsFor=/run
-ConditionPathExists=/run/fastnetmon/fastnetmon.conf
-After=
-After=vyos-router.service
-
-[Service]
-Type=simple
-WorkingDirectory=/run/fastnetmon
-PIDFile=/run/fastnetmon.pid
-ExecStart=
-ExecStart=/usr/sbin/fastnetmon --configuration_file /run/fastnetmon/fastnetmon.conf
diff --git a/src/etc/systemd/system/kea-ctrl-agent.service.d/override.conf b/src/etc/systemd/system/kea-ctrl-agent.service.d/override.conf
deleted file mode 100644
index c74fafb42..000000000
--- a/src/etc/systemd/system/kea-ctrl-agent.service.d/override.conf
+++ /dev/null
@@ -1,10 +0,0 @@
-[Unit]
-After=
-After=vyos-router.service
-ConditionFileNotEmpty=
-
-[Service]
-ExecStart=
-ExecStart=/usr/sbin/kea-ctrl-agent -c /run/kea/kea-ctrl-agent.conf
-AmbientCapabilities=CAP_NET_BIND_SERVICE
-CapabilityBoundingSet=CAP_NET_BIND_SERVICE
diff --git a/src/etc/systemd/system/kea-dhcp-ddns-server.service.d/override.conf b/src/etc/systemd/system/kea-dhcp-ddns-server.service.d/override.conf
new file mode 100644
index 000000000..cdfdea8eb
--- /dev/null
+++ b/src/etc/systemd/system/kea-dhcp-ddns-server.service.d/override.conf
@@ -0,0 +1,7 @@
+[Unit]
+After=
+After=vyos-router.service
+
+[Service]
+ExecStart=
+ExecStart=/usr/sbin/kea-dhcp-ddns -c /run/kea/kea-dhcp-ddns.conf
diff --git a/src/helpers/geoip-update.py b/src/helpers/geoip-update.py
index 34accf2cc..061c95401 100755
--- a/src/helpers/geoip-update.py
+++ b/src/helpers/geoip-update.py
@@ -25,20 +25,19 @@ def get_config(config=None):
conf = config
else:
conf = ConfigTreeQuery()
- base = ['firewall']
- if not conf.exists(base):
- return None
-
- return conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True,
- no_tag_node_value_mangle=True)
+ return (
+ conf.get_config_dict(['firewall'], key_mangling=('-', '_'), get_first_key=True,
+ no_tag_node_value_mangle=True) if conf.exists(['firewall']) else None,
+ conf.get_config_dict(['policy'], key_mangling=('-', '_'), get_first_key=True,
+ no_tag_node_value_mangle=True) if conf.exists(['policy']) else None,
+ )
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("--force", help="Force update", action="store_true")
args = parser.parse_args()
- firewall = get_config()
-
- if not geoip_update(firewall, force=args.force):
+ firewall, policy = get_config()
+ if not geoip_update(firewall=firewall, policy=policy, force=args.force):
sys.exit(1)
diff --git a/src/init/vyos-router b/src/init/vyos-router
index ab3cc42cb..8584234b3 100755
--- a/src/init/vyos-router
+++ b/src/init/vyos-router
@@ -417,6 +417,7 @@ gen_duid ()
start ()
{
+ echo -e "Initializing VyOS router\033[0m"
# reset and clean config files
security_reset || log_failure_msg "security reset failed"
@@ -459,6 +460,14 @@ start ()
nfct helper add tns inet6 tcp
nft --file /usr/share/vyos/vyos-firewall-init.conf || log_failure_msg "could not initiate firewall rules"
+ # Ensure rsyslog is the default syslog daemon
+ SYSTEMD_SYSLOG="/etc/systemd/system/syslog.service"
+ SYSTEMD_RSYSLOG="/lib/systemd/system/rsyslog.service"
+ if [ ! -L ${SYSTEMD_SYSLOG} ] || [ "$(readlink -f ${SYSTEMD_SYSLOG})" != "${SYSTEMD_RSYSLOG}" ]; then
+ ln -sf ${SYSTEMD_RSYSLOG} ${SYSTEMD_SYSLOG}
+ systemctl daemon-reload
+ fi
+
# 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_syslog.py || log_failure_msg "could not reset syslog"
@@ -517,7 +526,6 @@ start ()
cleanup_post_commit_hooks
- log_daemon_msg "Starting VyOS router"
disabled migrate || migrate_bootfile
restore_if_missing_preconfig_script
@@ -557,6 +565,9 @@ start ()
if [[ ! -z "$tmp" ]]; then
vtysh -c "rpki start"
fi
+
+ # Start netplug daemon
+ systemctl start netplug.service
}
stop()
@@ -574,8 +585,8 @@ stop()
umount ${vyatta_configdir}
log_action_end_msg $?
+ systemctl stop netplug.service
systemctl stop vyconfd.service
-
systemctl stop frr.service
unmount_encrypted_config
diff --git a/src/migration-scripts/dhcp-server/7-to-8 b/src/migration-scripts/dhcp-server/7-to-8
index 7fcb62e86..d0f9455bb 100644
--- a/src/migration-scripts/dhcp-server/7-to-8
+++ b/src/migration-scripts/dhcp-server/7-to-8
@@ -41,9 +41,6 @@ def migrate(config: ConfigTree) -> None:
for network in config.list_nodes(base + ['shared-network-name']):
base_network = base + ['shared-network-name', network]
- if config.exists(base_network + ['ping-check']):
- config.delete(base_network + ['ping-check'])
-
if config.exists(base_network + ['shared-network-parameters']):
config.delete(base_network +['shared-network-parameters'])
@@ -57,9 +54,6 @@ def migrate(config: ConfigTree) -> None:
if config.exists(base_subnet + ['enable-failover']):
config.delete(base_subnet + ['enable-failover'])
- if config.exists(base_subnet + ['ping-check']):
- config.delete(base_subnet + ['ping-check'])
-
if config.exists(base_subnet + ['subnet-parameters']):
config.delete(base_subnet + ['subnet-parameters'])
diff --git a/src/migration-scripts/ids/1-to-2 b/src/migration-scripts/ids/1-to-2
new file mode 100644
index 000000000..4c0333c88
--- /dev/null
+++ b/src/migration-scripts/ids/1-to-2
@@ -0,0 +1,30 @@
+# Copyright 2025 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/>.
+
+# T: Migrate threshold and add new threshold types
+
+from vyos.configtree import ConfigTree
+
+# The old 'service ids' path was only used for FastNetMon
+# Suricata is in 'service suricata',
+# so this isn't an overreach
+base = ['service', 'ids']
+
+def migrate(config: ConfigTree) -> None:
+ if not config.exists(base):
+ # Nothing to do
+ return
+ else:
+ config.delete(base)
diff --git a/src/op_mode/image_installer.py b/src/op_mode/image_installer.py
index 9c17d0229..2660309a5 100755
--- a/src/op_mode/image_installer.py
+++ b/src/op_mode/image_installer.py
@@ -24,7 +24,9 @@ from glob import glob
from sys import exit
from os import environ
from os import readlink
-from os import getpid, getppid
+from os import getpid
+from os import getppid
+from json import loads
from typing import Union
from urllib.parse import urlparse
from passlib.hosts import linux_context
@@ -35,15 +37,23 @@ from psutil import disk_partitions
from vyos.base import Warning
from vyos.configtree import ConfigTree
from vyos.remote import download
-from vyos.system import disk, grub, image, compat, raid, SYSTEM_CFG_VER
+from vyos.system import disk
+from vyos.system import grub
+from vyos.system import image
+from vyos.system import compat
+from vyos.system import raid
+from vyos.system import SYSTEM_CFG_VER
+from vyos.system import grub_util
from vyos.template import render
from vyos.utils.auth import (
DEFAULT_PASSWORD,
EPasswdStrength,
evaluate_strength
)
+from vyos.utils.dict import dict_search
from vyos.utils.io import ask_input, ask_yes_no, select_entry
from vyos.utils.file import chmod_2775
+from vyos.utils.file import read_file
from vyos.utils.process import cmd, run, rc_cmd
from vyos.version import get_version_data
@@ -74,6 +84,7 @@ MSG_INPUT_CONFIG_FOUND: str = 'An active configuration was found. Would you like
MSG_INPUT_CONFIG_CHOICE: str = 'The following config files are available for boot:'
MSG_INPUT_CONFIG_CHOOSE: str = 'Which file would you like as boot config?'
MSG_INPUT_IMAGE_NAME: str = 'What would you like to name this image?'
+MSG_INPUT_IMAGE_NAME_TAKEN: str = 'There is already an installed image by that name; please choose again'
MSG_INPUT_IMAGE_DEFAULT: str = 'Would you like to set the new image as the default one for boot?'
MSG_INPUT_PASSWORD: str = 'Please enter a password for the "vyos" user:'
MSG_INPUT_PASSWORD_CONFIRM: str = 'Please confirm password for the "vyos" user:'
@@ -476,6 +487,25 @@ def setup_grub(root_dir: str) -> None:
render(grub_cfg_menu, grub.TMPL_GRUB_MENU, {})
render(grub_cfg_options, grub.TMPL_GRUB_OPTS, {})
+def get_cli_kernel_options(config_file: str) -> list:
+ config = ConfigTree(read_file(config_file))
+ config_dict = loads(config.to_json())
+ kernel_options = dict_search('system.option.kernel', config_dict)
+ cmdline_options = []
+
+ # XXX: This code path and if statements must be kept in sync with the Kernel
+ # option handling in system_options.py:generate(). This occurance is used
+ # for having the appropriate options passed to GRUB after an image upgrade!
+ if 'disable-mitigations' in kernel_options:
+ cmdline_options.append('mitigations=off')
+ if 'disable-power-saving' in kernel_options:
+ cmdline_options.append('intel_idle.max_cstate=0 processor.max_cstate=1')
+ if 'amd-pstate-driver' in kernel_options:
+ mode = kernel_options['amd-pstate-driver']
+ cmdline_options.append(
+ f'initcall_blacklist=acpi_cpufreq_init amd_pstate={mode}')
+
+ return cmdline_options
def configure_authentication(config_file: str, password: str) -> None:
"""Write encrypted password to config file
@@ -490,10 +520,7 @@ def configure_authentication(config_file: str, password: str) -> None:
plaintext exposed
"""
encrypted_password = linux_context.hash(password)
-
- with open(config_file) as f:
- config_string = f.read()
-
+ config_string = read_file(config_file)
config = ConfigTree(config_string)
config.set([
'system', 'login', 'user', 'vyos', 'authentication',
@@ -984,8 +1011,12 @@ def add_image(image_path: str, vrf: str = None, username: str = '',
f'Adding image would downgrade image tools to v.{cfg_ver}; disallowed')
if not no_prompt:
+ versions = grub.version_list()
while True:
image_name: str = ask_input(MSG_INPUT_IMAGE_NAME, version_name)
+ if image_name in versions:
+ print(MSG_INPUT_IMAGE_NAME_TAKEN)
+ continue
if image.validate_name(image_name):
break
print(MSG_WARN_IMAGE_NAME_WRONG)
@@ -1040,6 +1071,12 @@ def add_image(image_path: str, vrf: str = None, username: str = '',
if set_as_default:
grub.set_default(image_name, root_dir)
+ cmdline_options = get_cli_kernel_options(
+ f'{target_config_dir}/config.boot')
+ grub_util.update_kernel_cmdline_options(' '.join(cmdline_options),
+ root_dir=root_dir,
+ version=image_name)
+
except OSError as e:
# if no space error, remove image dir and cleanup
if e.errno == ENOSPC:
diff --git a/src/services/vyos-conntrack-logger b/src/services/vyos-conntrack-logger
index 9c31b465f..ec0e1f717 100755
--- a/src/services/vyos-conntrack-logger
+++ b/src/services/vyos-conntrack-logger
@@ -15,10 +15,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import argparse
-import grp
import logging
import multiprocessing
-import os
import queue
import signal
import socket
diff --git a/src/services/vyos-domain-resolver b/src/services/vyos-domain-resolver
index aba5ba9db..4419fc4a7 100755
--- a/src/services/vyos-domain-resolver
+++ b/src/services/vyos-domain-resolver
@@ -92,12 +92,14 @@ def resolve(domains, ipv6=False):
for domain in domains:
resolved = fqdn_resolve(domain, ipv6=ipv6)
+ cache_key = f'{domain}_ipv6' if ipv6 else domain
+
if resolved and cache:
- domain_state[domain] = resolved
+ domain_state[cache_key] = resolved
elif not resolved:
- if domain not in domain_state:
+ if cache_key not in domain_state:
continue
- resolved = domain_state[domain]
+ resolved = domain_state[cache_key]
ip_list = ip_list | resolved
return ip_list
diff --git a/src/services/vyos-hostsd b/src/services/vyos-hostsd
index 1ba90471e..44f03586c 100755
--- a/src/services/vyos-hostsd
+++ b/src/services/vyos-hostsd
@@ -233,10 +233,7 @@
# }
import os
-import sys
-import time
import json
-import signal
import traceback
import re
import logging
@@ -245,7 +242,6 @@ import zmq
from voluptuous import Schema, MultipleInvalid, Required, Any
from collections import OrderedDict
from vyos.utils.file import makedir
-from vyos.utils.permission import chown
from vyos.utils.permission import chmod_755
from vyos.utils.process import popen
from vyos.utils.process import process_named_running
diff --git a/src/systemd/netplug.service b/src/systemd/netplug.service
new file mode 100644
index 000000000..928c553e8
--- /dev/null
+++ b/src/systemd/netplug.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Network cable hotplug management daemon
+Documentation=man:netplugd(8)
+After=vyos-router.service
+
+[Service]
+Type=forking
+PIDFile=/run/netplugd.pid
+ExecStart=/sbin/netplugd -c /etc/netplug/netplugd.conf -p /run/netplugd.pid
diff --git a/src/systemd/vyos.target b/src/systemd/vyos.target
index 47c91c1cc..ea1593fe9 100644
--- a/src/systemd/vyos.target
+++ b/src/systemd/vyos.target
@@ -1,3 +1,3 @@
[Unit]
Description=VyOS target
-After=multi-user.target
+After=multi-user.target vyos-grub-update.service systemd-sysctl.service