summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--interface-definitions/include/interface/mtu-68-16000.xml.i1
-rw-r--r--interface-definitions/interfaces_bonding.xml.in3
-rw-r--r--interface-definitions/interfaces_bridge.xml.in3
-rw-r--r--interface-definitions/interfaces_dummy.xml.in3
-rw-r--r--interface-definitions/interfaces_vti.xml.in3
-rw-r--r--interface-definitions/interfaces_wireguard.xml.in2
-rw-r--r--python/vyos/configverify.py6
-rw-r--r--python/vyos/utils/io.py12
-rw-r--r--smoketest/scripts/cli/base_interfaces_test.py3
-rwxr-xr-xsrc/conf_mode/interfaces_ethernet.py13
-rwxr-xr-xsrc/conf_mode/service_dhcp-server.py7
-rwxr-xr-xsrc/conf_mode/service_dhcpv6-server.py7
-rwxr-xr-xsrc/conf_mode/system_login.py26
-rwxr-xr-xsrc/op_mode/conntrack.py23
-rwxr-xr-xsrc/op_mode/image_installer.py16
15 files changed, 102 insertions, 26 deletions
diff --git a/interface-definitions/include/interface/mtu-68-16000.xml.i b/interface-definitions/include/interface/mtu-68-16000.xml.i
index cb666f470..df1b7b716 100644
--- a/interface-definitions/include/interface/mtu-68-16000.xml.i
+++ b/interface-definitions/include/interface/mtu-68-16000.xml.i
@@ -11,6 +11,5 @@
</constraint>
<constraintErrorMessage>MTU must be between 68 and 16000</constraintErrorMessage>
</properties>
- <defaultValue>1500</defaultValue>
</leafNode>
<!-- include end -->
diff --git a/interface-definitions/interfaces_bonding.xml.in b/interface-definitions/interfaces_bonding.xml.in
index 62ee0bdc7..92c0911db 100644
--- a/interface-definitions/interfaces_bonding.xml.in
+++ b/interface-definitions/interfaces_bonding.xml.in
@@ -261,6 +261,9 @@
</children>
</node>
#include <include/interface/mtu-68-16000.xml.i>
+ <leafNode name="mtu">
+ <defaultValue>1500</defaultValue>
+ </leafNode>
<leafNode name="primary">
<properties>
<help>Primary device interface</help>
diff --git a/interface-definitions/interfaces_bridge.xml.in b/interface-definitions/interfaces_bridge.xml.in
index 7fb5f121a..29dd61df5 100644
--- a/interface-definitions/interfaces_bridge.xml.in
+++ b/interface-definitions/interfaces_bridge.xml.in
@@ -41,6 +41,9 @@
#include <include/interface/disable.xml.i>
#include <include/interface/vrf.xml.i>
#include <include/interface/mtu-68-16000.xml.i>
+ <leafNode name="mtu">
+ <defaultValue>1500</defaultValue>
+ </leafNode>
<leafNode name="forwarding-delay">
<properties>
<help>Forwarding delay</help>
diff --git a/interface-definitions/interfaces_dummy.xml.in b/interface-definitions/interfaces_dummy.xml.in
index ef8ee78e7..36b4e41f2 100644
--- a/interface-definitions/interfaces_dummy.xml.in
+++ b/interface-definitions/interfaces_dummy.xml.in
@@ -46,6 +46,9 @@
</children>
</node>
#include <include/interface/mtu-68-16000.xml.i>
+ <leafNode name="mtu">
+ <defaultValue>1500</defaultValue>
+ </leafNode>
#include <include/interface/mirror.xml.i>
#include <include/interface/netns.xml.i>
#include <include/interface/redirect.xml.i>
diff --git a/interface-definitions/interfaces_vti.xml.in b/interface-definitions/interfaces_vti.xml.in
index 158d9afd0..39fb3131e 100644
--- a/interface-definitions/interfaces_vti.xml.in
+++ b/interface-definitions/interfaces_vti.xml.in
@@ -22,6 +22,9 @@
#include <include/interface/ipv4-options.xml.i>
#include <include/interface/ipv6-options.xml.i>
#include <include/interface/mtu-68-16000.xml.i>
+ <leafNode name="mtu">
+ <defaultValue>1500</defaultValue>
+ </leafNode>
#include <include/interface/mirror.xml.i>
#include <include/interface/redirect.xml.i>
#include <include/interface/vrf.xml.i>
diff --git a/interface-definitions/interfaces_wireguard.xml.in b/interface-definitions/interfaces_wireguard.xml.in
index fba1064ef..ce49de038 100644
--- a/interface-definitions/interfaces_wireguard.xml.in
+++ b/interface-definitions/interfaces_wireguard.xml.in
@@ -21,10 +21,10 @@
#include <include/interface/disable.xml.i>
#include <include/port-number.xml.i>
#include <include/interface/mtu-68-16000.xml.i>
- #include <include/interface/mirror.xml.i>
<leafNode name="mtu">
<defaultValue>1420</defaultValue>
</leafNode>
+ #include <include/interface/mirror.xml.i>
#include <include/interface/ipv4-options.xml.i>
#include <include/interface/ipv6-options.xml.i>
<leafNode name="fwmark">
diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py
index 18642877a..4cb84194a 100644
--- a/python/vyos/configverify.py
+++ b/python/vyos/configverify.py
@@ -60,8 +60,8 @@ def verify_mtu_parent(config, parent):
mtu = int(config['mtu'])
parent_mtu = int(parent['mtu'])
if mtu > parent_mtu:
- raise ConfigError(f'Interface MTU ({mtu}) too high, ' \
- f'parent interface MTU is {parent_mtu}!')
+ raise ConfigError(f'Interface MTU "{mtu}" too high, ' \
+ f'parent interface MTU is "{parent_mtu}"!')
def verify_mtu_ipv6(config):
"""
@@ -76,7 +76,7 @@ def verify_mtu_ipv6(config):
if int(config['mtu']) < min_mtu:
interface = config['ifname']
error_msg = f'IPv6 address will be configured on interface "{interface}",\n' \
- f'the required minimum MTU is {min_mtu}!'
+ f'the required minimum MTU is "{min_mtu}"!'
if 'address' in config:
for address in config['address']:
diff --git a/python/vyos/utils/io.py b/python/vyos/utils/io.py
index 0afaf695c..7e6045291 100644
--- a/python/vyos/utils/io.py
+++ b/python/vyos/utils/io.py
@@ -13,7 +13,7 @@
# 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/>.
-from typing import Callable
+from typing import Callable, Optional
def print_error(str='', end='\n'):
"""
@@ -81,7 +81,8 @@ def is_dumb_terminal():
return os.getenv('TERM') in ['vt100', 'dumb']
def select_entry(l: list, list_msg: str = '', prompt_msg: str = '',
- list_format: Callable = None,) -> str:
+ list_format: Optional[Callable] = None,
+ default_entry: Optional[int] = None) -> str:
"""Select an entry from a list
Args:
@@ -99,6 +100,9 @@ def select_entry(l: list, list_msg: str = '', prompt_msg: str = '',
print(f'\t{i}: {list_format(e)}')
else:
print(f'\t{i}: {e}')
- select = ask_input(prompt_msg, numeric_only=True,
- valid_responses=range(1, len(l)+1))
+ valid_entry = range(1, len(l)+1)
+ if default_entry and default_entry not in valid_entry:
+ default_entry = None
+ select = ask_input(prompt_msg, default=default_entry, numeric_only=True,
+ valid_responses=valid_entry)
return next(filter(lambda x: x[0] == select, en))[1]
diff --git a/smoketest/scripts/cli/base_interfaces_test.py b/smoketest/scripts/cli/base_interfaces_test.py
index a106ebe61..9be2c2f1a 100644
--- a/smoketest/scripts/cli/base_interfaces_test.py
+++ b/smoketest/scripts/cli/base_interfaces_test.py
@@ -519,8 +519,7 @@ class BasicInterfaceTest:
base = self._base_path + [interface, 'vif', vlan]
self.cli_set(base + ['mtu', mtu_9000])
- # check validate() - VIF MTU must not be larger the parent interface
- # MTU size.
+ # check validate() - Interface MTU "9000" too high, parent interface MTU is "1500"!
with self.assertRaises(ConfigSessionError):
self.cli_commit()
diff --git a/src/conf_mode/interfaces_ethernet.py b/src/conf_mode/interfaces_ethernet.py
index 41efdb03c..6da7e6a69 100755
--- a/src/conf_mode/interfaces_ethernet.py
+++ b/src/conf_mode/interfaces_ethernet.py
@@ -152,6 +152,19 @@ def get_config(config=None):
base = ['interfaces', 'ethernet']
ifname, ethernet = get_interface_dict(conf, base, with_pki=True)
+ # T5862 - default MTU is not acceptable in some environments
+ # There are cloud environments available where the maximum supported
+ # ethernet MTU is e.g. 1450 bytes, thus we clamp this to the adapters
+ # maximum MTU value or 1500 bytes - whatever is lower
+ if 'mtu' not in ethernet:
+ try:
+ ethernet['mtu'] = '1500'
+ max_mtu = EthernetIf(ifname).get_max_mtu()
+ if max_mtu < int(ethernet['mtu']):
+ ethernet['mtu'] = str(max_mtu)
+ except:
+ pass
+
if 'is_bond_member' in ethernet:
update_bond_options(conf, ethernet)
diff --git a/src/conf_mode/service_dhcp-server.py b/src/conf_mode/service_dhcp-server.py
index 3b9198ed0..e89448e2d 100755
--- a/src/conf_mode/service_dhcp-server.py
+++ b/src/conf_mode/service_dhcp-server.py
@@ -16,6 +16,7 @@
import os
+from glob import glob
from ipaddress import ip_address
from ipaddress import ip_network
from netaddr import IPRange
@@ -28,6 +29,7 @@ from vyos.template import render
from vyos.utils.dict import dict_search
from vyos.utils.dict import dict_search_args
from vyos.utils.file import chmod_775
+from vyos.utils.file import chown
from vyos.utils.file import makedir
from vyos.utils.file import write_file
from vyos.utils.process import call
@@ -42,6 +44,7 @@ ctrl_config_file = '/run/kea/kea-ctrl-agent.conf'
ctrl_socket = '/run/kea/dhcp4-ctrl-socket'
config_file = '/run/kea/kea-dhcp4.conf'
lease_file = '/config/dhcp/dhcp4-leases.csv'
+lease_file_glob = '/config/dhcp/dhcp4-leases*'
systemd_override = r'/run/systemd/system/kea-ctrl-agent.service.d/10-override.conf'
user_group = '_kea'
@@ -354,6 +357,10 @@ def generate(dhcp):
makedir(lease_dir, group='vyattacfg')
chmod_775(lease_dir)
+ # Ensure correct permissions on lease files + backups
+ for file in glob(lease_file_glob):
+ chown(file, user=user_group, group='vyattacfg')
+
# Create lease file if necessary and let kea own it - 'kea-lfc' expects it that way
if not os.path.exists(lease_file):
write_file(lease_file, '', user=user_group, group=user_group, mode=0o644)
diff --git a/src/conf_mode/service_dhcpv6-server.py b/src/conf_mode/service_dhcpv6-server.py
index add83eb0d..c7333dd3a 100755
--- a/src/conf_mode/service_dhcpv6-server.py
+++ b/src/conf_mode/service_dhcpv6-server.py
@@ -16,6 +16,7 @@
import os
+from glob import glob
from ipaddress import ip_address
from ipaddress import ip_network
from sys import exit
@@ -24,6 +25,7 @@ from vyos.config import Config
from vyos.template import render
from vyos.utils.process import call
from vyos.utils.file import chmod_775
+from vyos.utils.file import chown
from vyos.utils.file import makedir
from vyos.utils.file import write_file
from vyos.utils.dict import dict_search
@@ -35,6 +37,7 @@ airbag.enable()
config_file = '/run/kea/kea-dhcp6.conf'
ctrl_socket = '/run/kea/dhcp6-ctrl-socket'
lease_file = '/config/dhcp/dhcp6-leases.csv'
+lease_file_glob = '/config/dhcp/dhcp6-leases*'
user_group = '_kea'
def get_config(config=None):
@@ -224,6 +227,10 @@ def generate(dhcpv6):
makedir(lease_dir, group='vyattacfg')
chmod_775(lease_dir)
+ # Ensure correct permissions on lease files + backups
+ for file in glob(lease_file_glob):
+ chown(file, user=user_group, group='vyattacfg')
+
# Create lease file if necessary and let kea own it - 'kea-lfc' expects it that way
if not os.path.exists(lease_file):
write_file(lease_file, '', user=user_group, group=user_group, mode=0o644)
diff --git a/src/conf_mode/system_login.py b/src/conf_mode/system_login.py
index 49306c894..20121f170 100755
--- a/src/conf_mode/system_login.py
+++ b/src/conf_mode/system_login.py
@@ -336,27 +336,31 @@ def apply(login):
command += f' --groups frr,frrvty,vyattacfg,sudo,adm,dip,disk,_kea {user}'
try:
cmd(command)
- # we should not rely on the value stored in
- # user_config['home_directory'], as a crazy user will choose
- # username root or any other system user which will fail.
+ # we should not rely on the value stored in user_config['home_directory'], as a
+ # crazy user will choose username root or any other system user which will fail.
#
# XXX: Should we deny using root at all?
home_dir = getpwnam(user).pw_dir
- # T5875: ensure UID is properly set on home directory if user is re-added
- # the home directory will always exist, as it's created above by --create-home,
- # retrieve current owner of home directory and adjust it on demand
- dir_owner = getpwuid(os.stat(home_dir).st_uid).pw_name
- if dir_owner != user:
- chown(home_dir, user=user, recursive=True)
-
+ # always re-render SSH keys with appropriate permissions
render(f'{home_dir}/.ssh/authorized_keys', 'login/authorized_keys.j2',
user_config, permission=0o600,
formater=lambda _: _.replace("&quot;", '"'),
user=user, group='users')
-
except Exception as e:
raise ConfigError(f'Adding user "{user}" raised exception: "{e}"')
+ # T5875: ensure UID is properly set on home directory if user is re-added
+ # the home directory will always exist, as it's created above by --create-home,
+ # retrieve current owner of home directory and adjust on demand
+ dir_owner = None
+ try:
+ dir_owner = getpwuid(os.stat(home_dir).st_uid).pw_name
+ except:
+ pass
+
+ if dir_owner != user:
+ chown(home_dir, user=user, recursive=True)
+
# Generate 2FA/MFA One-Time-Pad configuration
if dict_search('authentication.otp.key', user_config):
enable_otp = True
diff --git a/src/op_mode/conntrack.py b/src/op_mode/conntrack.py
index 5687b9b00..c379c3e60 100755
--- a/src/op_mode/conntrack.py
+++ b/src/op_mode/conntrack.py
@@ -62,7 +62,7 @@ def _get_raw_data(family):
def _get_raw_statistics():
entries = []
- data = cmd('sudo conntrack -S')
+ data = cmd('sudo conntrack --stats')
data = data.replace(' \t', '').split('\n')
for entry in data:
entries.append(entry.split())
@@ -70,8 +70,25 @@ def _get_raw_statistics():
def get_formatted_statistics(entries):
- headers = ["CPU", "Found", "Invalid", "Insert", "Insert fail", "Drop", "Early drop", "Errors", "Search restart"]
- output = tabulate(entries, headers, numalign="left")
+ headers = [
+ "CPU",
+ "Found",
+ "Invalid",
+ "Insert",
+ "Insert fail",
+ "Drop",
+ "Early drop",
+ "Errors",
+ "Search restart",
+ "",
+ "",
+ ]
+ # Process each entry to extract and format the values after '='
+ processed_entries = [
+ [value.split('=')[-1] for value in entry]
+ for entry in entries
+ ]
+ output = tabulate(processed_entries, headers, numalign="left")
return output
diff --git a/src/op_mode/image_installer.py b/src/op_mode/image_installer.py
index 446c47cec..9f6949fb3 100755
--- a/src/op_mode/image_installer.py
+++ b/src/op_mode/image_installer.py
@@ -56,6 +56,8 @@ MSG_INFO_INSTALL_DISK_CONFIRM: str = 'Installation will delete all data on the d
MSG_INFO_INSTALL_RAID_CONFIRM: str = 'Installation will delete all data on both drives. Continue?'
MSG_INFO_INSTALL_PARTITONING: str = 'Creating partition table...'
MSG_INPUT_CONFIG_FOUND: str = 'An active configuration was found. Would you like to copy it to the new image?'
+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_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'
@@ -702,6 +704,10 @@ def install_image() -> None:
valid_responses=['K', 'S', 'U'])
console_dict: dict[str, str] = {'K': 'tty', 'S': 'ttyS', 'U': 'ttyUSB'}
+ config_boot_list = ['/opt/vyatta/etc/config/config.boot',
+ '/opt/vyatta/etc/config.boot.default']
+ default_config = config_boot_list[0]
+
disks: dict[str, int] = find_disks()
install_target: Union[disk.DiskDetails, raid.RaidDetails, None] = None
@@ -710,6 +716,14 @@ def install_image() -> None:
if install_target is None:
install_target = ask_single_disk(disks)
+ # if previous install was selected in search_previous_installation,
+ # directory /mnt/config was prepared for copy below; if not, prompt:
+ if not Path('/mnt/config').exists():
+ default_config: str = select_entry(config_boot_list,
+ MSG_INPUT_CONFIG_CHOICE,
+ MSG_INPUT_CONFIG_CHOOSE,
+ default_entry=1) # select_entry indexes from 1
+
# create directories for installation media
prepare_tmp_disr()
@@ -731,7 +745,7 @@ def install_image() -> None:
chown(target_config_dir, group='vyattacfg')
chmod_2775(target_config_dir)
# copy config
- copy('/opt/vyatta/etc/config/config.boot', target_config_dir)
+ copy(default_config, f'{target_config_dir}/config.boot')
configure_authentication(f'{target_config_dir}/config.boot',
user_password)
Path(f'{target_config_dir}/.vyatta_config').touch()