diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/vyos/ifconfig/control.py | 34 | ||||
| -rw-r--r-- | python/vyos/validate.py | 31 | 
2 files changed, 60 insertions, 5 deletions
| diff --git a/python/vyos/ifconfig/control.py b/python/vyos/ifconfig/control.py index 0958be642..a6fc8ac6c 100644 --- a/python/vyos/ifconfig/control.py +++ b/python/vyos/ifconfig/control.py @@ -15,6 +15,8 @@  import os +from inspect import signature +from inspect import _empty  from vyos import debug  from vyos.util import popen @@ -25,6 +27,7 @@ from vyos.ifconfig.section import Section  class Control(Section):      _command_get = {}      _command_set = {} +    _signature = {}      def __init__(self, **kargs):          # some commands (such as operation comands - show interfaces, etc.)  @@ -54,6 +57,30 @@ class Control(Section):          cmd = self._command_get[name]['shellcmd'].format(**config)          return self._command_get[name].get('format', lambda _: _)(self._cmd(cmd)) +    def _values(self, name, validate, value): +        """ +        looks at the validation function "validate" +        for the interface sysfs or command and +        returns a dict with the right options to call it +        """ +        if name not in self._signature: +            self._signature[name] = signature(validate) + +        values = {} + +        for k in self._signature[name].parameters: +            default = self._signature[name].parameters[k].default +            if default is not _empty: +                continue +            if k == 'self': +                values[k] = self +            elif k == 'ifname': +                values[k] = self.ifname +            else: +                values[k] = value + +        return values +      def _set_command(self, config, name, value):          """          Using the defined names, set data write to sysfs. @@ -64,7 +91,7 @@ class Control(Section):          validate = self._command_set[name].get('validate', None)          if validate:              try: -                validate(value) +                validate(**self._values(name, validate, value))              except Exception as e:                  raise e.__class__(f'Could not set {name}. {e}') @@ -124,7 +151,10 @@ class Control(Section):          validate = self._sysfs_set[name].get('validate', None)          if validate: -            validate(value) +            try: +                validate(**self._values(name, validate, value)) +            except Exception as e: +                raise e.__class__(f'Could not set {name}. {e}')          config = {**config, **{'value': value}} diff --git a/python/vyos/validate.py b/python/vyos/validate.py index 6304fa8de..9072c5817 100644 --- a/python/vyos/validate.py +++ b/python/vyos/validate.py @@ -13,10 +13,23 @@  # 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 json  import socket  import netifaces  import ipaddress +from vyos.util import cmd + +# Important note when you are adding new validation functions: +# +# The Control class will analyse the signature of the function in this file +# and will build the parameters to be passed to it. +# +# The parameter names "ifname" and "self" will get the Interface name and class +# parameters with default will be left unset +# all other paramters will receive the value to check + +  def is_ip(addr):      """      Check addr if it is an IPv4 or IPv6 address @@ -208,10 +221,21 @@ def assert_positive(n, smaller=0):          raise ValueError(f'{n} is smaller than {smaller}') -def assert_mtu(mtu, min=68, max=9000): +def assert_mtu(mtu, ifname):      assert_number(mtu) -    if int(mtu) < min or int(mtu) > max: -        raise ValueError(f'Invalid MTU size: "{mtu}"') + +    out = cmd(f'ip -j -d link show dev {ifname}') +    # [{"ifindex":2,"ifname":"eth0","flags":["BROADCAST","MULTICAST","UP","LOWER_UP"],"mtu":1500,"qdisc":"pfifo_fast","operstate":"UP","linkmode":"DEFAULT","group":"default","txqlen":1000,"link_type":"ether","address":"08:00:27:d9:5b:04","broadcast":"ff:ff:ff:ff:ff:ff","promiscuity":0,"min_mtu":46,"max_mtu":16110,"inet6_addr_gen_mode":"none","num_tx_queues":1,"num_rx_queues":1,"gso_max_size":65536,"gso_max_segs":65535}] +    parsed = json.loads(out)[0] +    min_mtu = int(parsed.get('min_mtu', '0')) +    # cur_mtu = parsed.get('mtu',0), +    max_mtu = int(parsed.get('max_mtu', '0')) +    cur_mtu = int(mtu) + +    if (min_mtu and cur_mtu < min_mtu) or cur_mtu < 68: +        raise ValueError(f'MTU is too small for interface "{ifname}": {mtu} < {min_mtu}') +    if (max_mtu and cur_mtu > max_mtu) or cur_mtu > 65536: +        raise ValueError(f'MTU is too small for interface "{ifname}": {mtu} > {max_mtu}')  def assert_mac(m): @@ -241,6 +265,7 @@ def assert_mac(m):      if octets[:5] == (0, 0, 94, 0, 1):          raise ValueError(f'{m} is a VRRP MAC address') +  def is_member(conf, interface, intftype=None):      """      Checks if passed interface is member of other interface of specified type. | 
