summaryrefslogtreecommitdiff
path: root/python/vyos
diff options
context:
space:
mode:
Diffstat (limited to 'python/vyos')
-rw-r--r--python/vyos/configdict.py11
-rw-r--r--python/vyos/configverify.py6
-rw-r--r--python/vyos/defaults.py2
-rw-r--r--python/vyos/firewall.py5
-rw-r--r--python/vyos/ifconfig/bridge.py20
-rw-r--r--python/vyos/ifconfig/ethernet.py8
-rw-r--r--python/vyos/ifconfig/pppoe.py37
-rw-r--r--python/vyos/ifconfig/section.py12
-rw-r--r--python/vyos/opmode.py2
-rw-r--r--python/vyos/template.py4
-rw-r--r--python/vyos/util.py49
11 files changed, 140 insertions, 16 deletions
diff --git a/python/vyos/configdict.py b/python/vyos/configdict.py
index 8f822a97d..912bc94f2 100644
--- a/python/vyos/configdict.py
+++ b/python/vyos/configdict.py
@@ -295,11 +295,18 @@ def is_source_interface(conf, interface, intftype=None):
"""
ret_val = None
intftypes = ['macsec', 'pppoe', 'pseudo-ethernet', 'tunnel', 'vxlan']
- if intftype not in intftypes + [None]:
+ if not intftype:
+ intftype = intftypes
+
+ if isinstance(intftype, str):
+ intftype = [intftype]
+ elif not isinstance(intftype, list):
+ raise ValueError(f'Interface type "{type(intftype)}" must be either str or list!')
+
+ if not all(x in intftypes for x in intftype):
raise ValueError(f'unknown interface type "{intftype}" or it can not '
'have a source-interface')
- intftype = intftypes if intftype == None else [intftype]
for it in intftype:
base = ['interfaces', it]
for intf in conf.list_nodes(base):
diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py
index 2ab3cb408..447ec795c 100644
--- a/python/vyos/configverify.py
+++ b/python/vyos/configverify.py
@@ -295,6 +295,12 @@ def verify_source_interface(config):
raise ConfigError(f'Invalid source-interface "{src_ifname}". Interface '
f'is already a member of bond "{bond_name}"!')
+ if 'is_source_interface' in config:
+ tmp = config['is_source_interface']
+ src_ifname = config['source_interface']
+ raise ConfigError(f'Can not use source-interface "{src_ifname}", it already ' \
+ f'belongs to interface "{tmp}"!')
+
def verify_dhcpv6(config):
"""
Common helper function used by interface implementations to perform
diff --git a/python/vyos/defaults.py b/python/vyos/defaults.py
index 09ae73eac..6894fc4da 100644
--- a/python/vyos/defaults.py
+++ b/python/vyos/defaults.py
@@ -26,7 +26,7 @@ directories = {
"templates": "/usr/share/vyos/templates/",
"certbot": "/config/auth/letsencrypt",
"api_schema": "/usr/libexec/vyos/services/api/graphql/graphql/schema/",
- "api_templates": "/usr/libexec/vyos/services/api/graphql/recipes/templates/",
+ "api_templates": "/usr/libexec/vyos/services/api/graphql/session/templates/",
"vyos_udev_dir": "/run/udev/vyos"
}
diff --git a/python/vyos/firewall.py b/python/vyos/firewall.py
index 3e2de4c3f..663c4394a 100644
--- a/python/vyos/firewall.py
+++ b/python/vyos/firewall.py
@@ -297,6 +297,11 @@ def parse_rule(rule_conf, fw_name, rule_id, ip_name):
if tcp_flags:
output.append(parse_tcp_flags(tcp_flags))
+ # TCP MSS
+ tcp_mss = dict_search_args(rule_conf, 'tcp', 'mss')
+ if tcp_mss:
+ output.append(f'tcp option maxseg size {tcp_mss}')
+
output.append('counter')
if 'set' in rule_conf:
diff --git a/python/vyos/ifconfig/bridge.py b/python/vyos/ifconfig/bridge.py
index 758967fbc..aa818bc5f 100644
--- a/python/vyos/ifconfig/bridge.py
+++ b/python/vyos/ifconfig/bridge.py
@@ -295,8 +295,24 @@ class BridgeIf(Interface):
self.del_port(member)
# enable/disable Vlan Filter
- vlan_filter = '1' if 'enable_vlan' in config else '0'
- self.set_vlan_filter(vlan_filter)
+ tmp = '1' if 'enable_vlan' in config else '0'
+ self.set_vlan_filter(tmp)
+
+ # add VLAN interfaces to local 'parent' bridge to allow forwarding
+ if 'enable_vlan' in config:
+ for vlan in config.get('vif_remove', {}):
+ # Remove old VLANs from the bridge
+ cmd = f'bridge vlan del dev {self.ifname} vid {vlan} self'
+ self._cmd(cmd)
+
+ for vlan in config.get('vif', {}):
+ cmd = f'bridge vlan add dev {self.ifname} vid {vlan} self'
+ self._cmd(cmd)
+
+ # VLAN of bridge parent interface is always 1. VLAN 1 is the default
+ # VLAN for all unlabeled packets
+ cmd = f'bridge vlan add dev {self.ifname} vid 1 pvid untagged self'
+ self._cmd(cmd)
tmp = dict_search('member.interface', config)
if tmp:
diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py
index 1280fc238..b8deb3311 100644
--- a/python/vyos/ifconfig/ethernet.py
+++ b/python/vyos/ifconfig/ethernet.py
@@ -236,7 +236,7 @@ class EthernetIf(Interface):
enabled, fixed = self.ethtool.get_large_receive_offload()
if enabled != state:
if not fixed:
- return self.set_interface('gro', 'on' if state else 'off')
+ return self.set_interface('lro', 'on' if state else 'off')
else:
print('Adapter does not support changing large-receive-offload settings!')
return False
@@ -273,7 +273,7 @@ class EthernetIf(Interface):
enabled, fixed = self.ethtool.get_scatter_gather()
if enabled != state:
if not fixed:
- return self.set_interface('gro', 'on' if state else 'off')
+ return self.set_interface('sg', 'on' if state else 'off')
else:
print('Adapter does not support changing scatter-gather settings!')
return False
@@ -293,7 +293,7 @@ class EthernetIf(Interface):
enabled, fixed = self.ethtool.get_tcp_segmentation_offload()
if enabled != state:
if not fixed:
- return self.set_interface('gro', 'on' if state else 'off')
+ return self.set_interface('tso', 'on' if state else 'off')
else:
print('Adapter does not support changing tcp-segmentation-offload settings!')
return False
@@ -359,5 +359,5 @@ class EthernetIf(Interface):
for rx_tx, size in config['ring_buffer'].items():
self.set_ring_buffer(rx_tx, size)
- # call base class first
+ # call base class last
super().update(config)
diff --git a/python/vyos/ifconfig/pppoe.py b/python/vyos/ifconfig/pppoe.py
index 63ffc8069..437fe0cae 100644
--- a/python/vyos/ifconfig/pppoe.py
+++ b/python/vyos/ifconfig/pppoe.py
@@ -1,4 +1,4 @@
-# Copyright 2020-2021 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2020-2022 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
@@ -14,6 +14,7 @@
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
from vyos.ifconfig.interface import Interface
+from vyos.validate import assert_range
from vyos.util import get_interface_config
@Interface.register
@@ -27,6 +28,21 @@ class PPPoEIf(Interface):
},
}
+ _sysfs_get = {
+ **Interface._sysfs_get,**{
+ 'accept_ra_defrtr': {
+ 'location': '/proc/sys/net/ipv6/conf/{ifname}/accept_ra_defrtr',
+ }
+ }
+ }
+
+ _sysfs_set = {**Interface._sysfs_set, **{
+ 'accept_ra_defrtr': {
+ 'validate': lambda value: assert_range(value, 0, 2),
+ 'location': '/proc/sys/net/ipv6/conf/{ifname}/accept_ra_defrtr',
+ },
+ }}
+
def _remove_routes(self, vrf=None):
# Always delete default routes when interface is removed
vrf_cmd = ''
@@ -70,6 +86,21 @@ class PPPoEIf(Interface):
""" Get a synthetic MAC address. """
return self.get_mac_synthetic()
+ def set_accept_ra_defrtr(self, enable):
+ """
+ Learn default router in Router Advertisement.
+ 1: enabled
+ 0: disable
+
+ Example:
+ >>> from vyos.ifconfig import PPPoEIf
+ >>> PPPoEIf('pppoe1').set_accept_ra_defrtr(0)
+ """
+ tmp = self.get_interface('accept_ra_defrtr')
+ if tmp == enable:
+ return None
+ self.set_interface('accept_ra_defrtr', enable)
+
def update(self, config):
""" General helper function which works on a dictionary retrived by
get_config_dict(). It's main intention is to consolidate the scattered
@@ -107,6 +138,10 @@ class PPPoEIf(Interface):
tmp = config['vrf']
vrf = f'-c "vrf {tmp}"'
+ # learn default router in Router Advertisement.
+ tmp = '0' if 'no_default_route' in config else '1'
+ self.set_accept_ra_defrtr(tmp)
+
if 'no_default_route' not in config:
# Set default route(s) pointing to PPPoE interface
distance = config['default_route_distance']
diff --git a/python/vyos/ifconfig/section.py b/python/vyos/ifconfig/section.py
index 91f667b65..5e98cd510 100644
--- a/python/vyos/ifconfig/section.py
+++ b/python/vyos/ifconfig/section.py
@@ -88,7 +88,7 @@ class Section:
raise ValueError(f'No type found for interface name: {name}')
@classmethod
- def _intf_under_section (cls,section=''):
+ def _intf_under_section (cls,section='',vlan=True):
"""
return a generator with the name of the configured interface
which are under a section
@@ -103,6 +103,9 @@ class Section:
if section and ifsection != section:
continue
+ if vlan == False and '.' in ifname:
+ continue
+
yield ifname
@classmethod
@@ -135,13 +138,14 @@ class Section:
return l
@classmethod
- def interfaces(cls, section=''):
+ def interfaces(cls, section='', vlan=True):
"""
return a list of the name of the configured interface which are under a section
- if no section is provided, then it returns all configured interfaces
+ if no section is provided, then it returns all configured interfaces.
+ If vlan is True, also Vlan subinterfaces will be returned
"""
- return cls._sort_interfaces(cls._intf_under_section(section))
+ return cls._sort_interfaces(cls._intf_under_section(section, vlan))
@classmethod
def _intf_with_feature(cls, feature=''):
diff --git a/python/vyos/opmode.py b/python/vyos/opmode.py
index 628f7b3a2..7e3545c87 100644
--- a/python/vyos/opmode.py
+++ b/python/vyos/opmode.py
@@ -105,6 +105,8 @@ def run(module):
subparser = subparsers.add_parser(function_name, help=functions[function_name].__doc__)
type_hints = typing.get_type_hints(functions[function_name])
+ if 'return' in type_hints:
+ del type_hints['return']
for opt in type_hints:
th = type_hints[opt]
diff --git a/python/vyos/template.py b/python/vyos/template.py
index eb7f06480..9804308c1 100644
--- a/python/vyos/template.py
+++ b/python/vyos/template.py
@@ -1,4 +1,4 @@
-# Copyright 2019-2020 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2019-2022 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
@@ -550,7 +550,7 @@ def nft_rule(rule_conf, fw_name, rule_id, ip_name='ip'):
@register_filter('nft_default_rule')
def nft_default_rule(fw_conf, fw_name):
output = ['counter']
- default_action = fw_conf.get('default_action', 'accept')
+ default_action = fw_conf['default_action']
if 'enable_default_log' in fw_conf:
action_suffix = default_action[:1].upper()
diff --git a/python/vyos/util.py b/python/vyos/util.py
index b86b1949c..325b630bc 100644
--- a/python/vyos/util.py
+++ b/python/vyos/util.py
@@ -471,6 +471,29 @@ def process_named_running(name):
return p.pid
return None
+def is_listen_port_bind_service(port: int, service: str) -> bool:
+ """Check if listen port bound to expected program name
+ :param port: Bind port
+ :param service: Program name
+ :return: bool
+
+ Example:
+ % is_listen_port_bind_service(443, 'nginx')
+ True
+ % is_listen_port_bind_service(443, 'ocservr-main')
+ False
+ """
+ from psutil import net_connections as connections
+ from psutil import Process as process
+ for connection in connections():
+ addr = connection.laddr
+ pid = connection.pid
+ pid_name = process(pid).name()
+ pid_port = addr.port
+ if service == pid_name and port == pid_port:
+ return True
+ return False
+
def seconds_to_human(s, separator=""):
""" Converts number of seconds passed to a human-readable
interval such as 1w4d18h35m59s
@@ -800,6 +823,32 @@ def dict_search_recursive(dict_object, key, path=[]):
for x in dict_search_recursive(j, key, new_path):
yield x
+def convert_data(data):
+ """Convert multiple types of data to types usable in CLI
+
+ Args:
+ data (str | bytes | list | OrderedDict): input data
+
+ Returns:
+ str | list | dict: converted data
+ """
+ from collections import OrderedDict
+
+ if isinstance(data, str):
+ return data
+ if isinstance(data, bytes):
+ return data.decode()
+ if isinstance(data, list):
+ list_tmp = []
+ for item in data:
+ list_tmp.append(convert_data(item))
+ return list_tmp
+ if isinstance(data, OrderedDict):
+ dict_tmp = {}
+ for key, value in data.items():
+ dict_tmp[key] = convert_data(value)
+ return dict_tmp
+
def get_bridge_fdb(interface):
""" Returns the forwarding database entries for a given interface """
if not os.path.exists(f'/sys/class/net/{interface}'):