summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2019-10-27 05:01:38 +0100
committerChristian Poessinger <christian@poessinger.com>2019-10-27 05:01:38 +0100
commit9805067e9d80ec1676cf2c2039be3136401c9fa3 (patch)
tree141f2063203ac5823eb3980b83646756f053ddbc
parent69a14678de1c4f9b35414cbb00f33330478e4c58 (diff)
parent556b528ef9cc1eca9d142ebe1f8f88cd02d536da (diff)
downloadvyos-1x-9805067e9d80ec1676cf2c2039be3136401c9fa3.tar.gz
vyos-1x-9805067e9d80ec1676cf2c2039be3136401c9fa3.zip
Merge branch 'current' of github.com:vyos/vyos-1x into equuleus
* 'current' of github.com:vyos/vyos-1x: snmp: T1769: remove TSM (Transport Security Mode) support snmp: T818: T1738: remove per user/trap engine id T1759: ioctl.pm/interface.pm rewrite
-rw-r--r--interface-definitions/snmp.xml52
-rw-r--r--python/vyos/iflag.py38
-rw-r--r--python/vyos/interface.py9
-rw-r--r--python/vyos/ioctl.py34
-rwxr-xr-xsrc/conf_mode/snmp.py92
-rwxr-xr-xsrc/migration-scripts/snmp/0-to-156
6 files changed, 142 insertions, 139 deletions
diff --git a/interface-definitions/snmp.xml b/interface-definitions/snmp.xml
index 1634bfb64..14aad90a0 100644
--- a/interface-definitions/snmp.xml
+++ b/interface-definitions/snmp.xml
@@ -307,15 +307,6 @@
</leafNode>
</children>
</node>
- <leafNode name="engineid">
- <properties>
- <help>Specifies the EngineID that uniquely identify an agent (e.g. 0xff42)</help>
- <constraint>
- <regex>^(0x){0,1}([0-9a-f][0-9a-f]){1,18}$</regex>
- </constraint>
- <constraintErrorMessage>ID must contain from 2 to 36 hex digits</constraintErrorMessage>
- </properties>
- </leafNode>
<leafNode name="port">
<properties>
<help>Specifies TCP/UDP port of destination SNMP traps/informs (default: '162')</help>
@@ -421,35 +412,6 @@
</leafNode>
</children>
</tagNode>
- <node name="tsm">
- <properties>
- <help>Specifies that SNMPv3 uses the Transport Security Model (TSM)</help>
- </properties>
- <children>
- <leafNode name="local-key">
- <properties>
- <help>Fingerprint of a TSM server certificate</help>
- <constraint>
- <regex>^[0-9A-F]{2}(:[0-9A-F]{2}){19}$</regex>
- </constraint>
- <constraintErrorMessage>Value can be finger print key or filename in /config/snmp/tls/certs</constraintErrorMessage>
- </properties>
- </leafNode>
- <leafNode name="port">
- <properties>
- <help>Defines the port used for TSM (default: '10161')</help>
- <valueHelp>
- <format>1-65535</format>
- <description>Numeric IP port</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- <constraintErrorMessage>Port number must be in range 1 to 65535</constraintErrorMessage>
- </properties>
- </leafNode>
- </children>
- </node>
<tagNode name="user">
<properties>
<help>Specifies the user with name username</help>
@@ -503,15 +465,6 @@
</leafNode>
</children>
</node>
- <leafNode name="engineid">
- <properties>
- <help>Specifies the EngineID that uniquely identify an agent (e.g. 0xff42)</help>
- <constraint>
- <regex>^(0x){0,1}([0-9a-f][0-9a-f]){1,18}$</regex>
- </constraint>
- <constraintErrorMessage>ID must contain from 2 to 36 hex digits</constraintErrorMessage>
- </properties>
- </leafNode>
<leafNode name="group">
<properties>
<help>Specifies group for user name</help>
@@ -582,11 +535,6 @@
</constraint>
</properties>
</leafNode>
- <leafNode name="tsm-key">
- <properties>
- <help>Specifies finger print or file name of TSM certificate</help>
- </properties>
- </leafNode>
</children>
</node>
</children>
diff --git a/python/vyos/iflag.py b/python/vyos/iflag.py
new file mode 100644
index 000000000..7ff8e5623
--- /dev/null
+++ b/python/vyos/iflag.py
@@ -0,0 +1,38 @@
+# Copyright 2019 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/>.
+
+from enum import Enum, unique, IntEnum
+
+
+class IFlag(IntEnum):
+ """ net/if.h interface flags """
+
+ IFF_UP = 0x1 #: Interface up/down status
+ IFF_BROADCAST = 0x2 #: Broadcast address valid
+ IFF_DEBUG = 0x4, #: Debugging
+ IFF_LOOPBACK = 0x8 #: Is loopback network
+ IFF_POINTOPOINT = 0x10 #: Is point-to-point link
+ IFF_NOTRAILERS = 0x20 #: Avoid use of trailers
+ IFF_RUNNING = 0x40 #: Resources allocated
+ IFF_NOARP = 0x80 #: No address resolution protocol
+ IFF_PROMISC = 0x100 #: Promiscuous mode
+ IFF_ALLMULTI = 0x200 #: Receive all multicast
+ IFF_MASTER = 0x400 #: Load balancer master
+ IFF_SLAVE = 0x800 #: Load balancer slave
+ IFF_MULTICAST = 0x1000 #: Supports multicast
+ IFF_PORTSEL = 0x2000 #: Media type adjustable
+ IFF_AUTOMEDIA = 0x4000 #: Automatic media type enabled
+ IFF_DYNAMIC = 0x8000 #: Is a dial-up device with dynamic address
+
diff --git a/python/vyos/interface.py b/python/vyos/interface.py
index 1aae6db60..cc726e5cc 100644
--- a/python/vyos/interface.py
+++ b/python/vyos/interface.py
@@ -16,6 +16,8 @@
import vyos
from vyos.config import Config
import vyos.interfaces
+import vyos.ioctl
+from vyos.iflag import IFlag
import re
import json
@@ -33,11 +35,18 @@ class Interface():
intf = None
intf_type = None
valid = False
+ flags = None
def __init__(self,intf):
self.intf = intf
self.intf_type = vyos.interfaces.get_type_of_interface(self.intf)
self.valid = (self.intf in vyos.interfaces.list_interfaces())
+ if (self.valid):
+ self.flags = vyos.ioctl.get_interface_flags(intf)
+
+ def up(self):
+ """ return whether interface is up or not """
+ return self.flags & IFlag.IFF_UP
def print_interface(self):
diff --git a/python/vyos/ioctl.py b/python/vyos/ioctl.py
new file mode 100644
index 000000000..e57d261e4
--- /dev/null
+++ b/python/vyos/ioctl.py
@@ -0,0 +1,34 @@
+# Copyright 2019 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/>.
+
+import os
+import fcntl, struct, sys
+from socket import *
+
+SIOCGIFFLAGS = 0x8913
+
+def get_terminal_size():
+ """ pull the terminal size """
+ """ rows,cols = vyos.ioctl.get_terminal_size() """
+ columns, rows = os.get_terminal_size(0)
+ return (rows,columns)
+
+def get_interface_flags(intf):
+ """ Pull the SIOCGIFFLAGS """
+ nullif = '\0'*256
+ sock = socket(AF_INET, SOCK_DGRAM)
+ raw = fcntl.ioctl(sock.fileno(), SIOCGIFFLAGS, intf + nullif)
+ flags, = struct.unpack('H', raw[16:18])
+ return flags
diff --git a/src/conf_mode/snmp.py b/src/conf_mode/snmp.py
index cba1fe319..74c17fff6 100755
--- a/src/conf_mode/snmp.py
+++ b/src/conf_mode/snmp.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2018 VyOS maintainers and contributors
+# Copyright (C) 2018-2019 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
@@ -13,8 +13,6 @@
#
# 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 sys
import os
@@ -78,7 +76,7 @@ createUser {{ u.name }}
{%- elif u.authPassword %}
createUser {{ u.name }} {{ u.authProtocol | upper }} "{{ u.authPassword }}" {{ u.privProtocol | upper }} {{ u.privPassword }}
{%- else %}
-usmUser 1 3 {{ u.engineID }} "{{ u.name }}" "{{ u.name }}" NULL {{ u.authOID }} {{ u.authMasterKey }} {{ u.privOID }} {{ u.privMasterKey }} 0x
+usmUser 1 3 {{ v3_engineid }} "{{ u.name }}" "{{ u.name }}" NULL {{ u.authOID }} {{ u.authMasterKey }} {{ u.privOID }} {{ u.privMasterKey }} 0x
{%- endif %}
{%- endfor %}
@@ -117,9 +115,6 @@ monitor -r 10 -e linkDownTrap "Generate linkDown" ifOperStatus == 2
########################
# configurable section #
########################
-{% if v3_tsm_key %}
-[snmp] localCert {{ v3_tsm_key }}
-{%- endif %}
# Default system description is VyOS version
sysDescr VyOS {{ version }}
@@ -130,7 +125,7 @@ SysDescr {{ description }}
{%- endif %}
# Listen
-agentaddress unix:/run/snmpd.socket{% if listen_on %}{% for li in listen_on %},{{ li }}{% endfor %}{% else %},udp:161,udp6:161{% endif %}{% if v3_tsm_key %},tlstcp:{{ v3_tsm_port }},dtlsudp::{{ v3_tsm_port }}{% endif %}
+agentaddress unix:/run/snmpd.socket{% if listen_on %}{% for li in listen_on %},{{ li }}{% endfor %}{% else %},udp:161,udp6:161{% endif %}
# SNMP communities
{%- for c in communities %}
@@ -192,18 +187,16 @@ view {{ v.name }} included .{{ oid.oid }}
# context sec.model sec.level match read write notif
{%- for g in v3_groups %}
access {{ g.name }} "" usm {{ g.seclevel }} exact {{ g.view }} {% if g.mode == 'ro' %}none{% else %}{{ g.view }}{% endif %} none
-access {{ g.name }} "" tsm {{ g.seclevel }} exact {{ g.view }} {% if g.mode == 'ro' %}none{% else %}{{ g.view }}{% endif %} none
{%- endfor %}
# trap-target
{%- for t in v3_traps %}
-trapsess -v 3 {{ '-Ci' if t.type == 'inform' }} -e {{ t.engineID }} -u {{ t.secName }} -l {{ t.secLevel }} -a {{ t.authProtocol }} {% if t.authPassword %}-A {{ t.authPassword }}{% elif t.authMasterKey %}-3m {{ t.authMasterKey }}{% endif %} -x {{ t.privProtocol }} {% if t.privPassword %}-X {{ t.privPassword }}{% elif t.privMasterKey %}-3M {{ t.privMasterKey }}{% endif %} {{ t.ipProto }}:{{ t.ipAddr }}:{{ t.ipPort }}
+trapsess -v 3 {{ '-Ci' if t.type == 'inform' }} -e {{ v3_engineid }} -u {{ t.secName }} -l {{ t.secLevel }} -a {{ t.authProtocol }} {% if t.authPassword %}-A {{ t.authPassword }}{% elif t.authMasterKey %}-3m {{ t.authMasterKey }}{% endif %} -x {{ t.privProtocol }} {% if t.privPassword %}-X {{ t.privPassword }}{% elif t.privMasterKey %}-3M {{ t.privMasterKey }}{% endif %} {{ t.ipProto }}:{{ t.ipAddr }}:{{ t.ipPort }}
{%- endfor %}
# group
{%- for u in v3_users %}
group {{ u.group }} usm {{ u.name }}
-group {{ u.group }} tsm {{ u.name }}
{% endfor %}
{%- endif %}
@@ -244,8 +237,6 @@ default_config_data = {
'v3_engineid': '',
'v3_groups': [],
'v3_traps': [],
- 'v3_tsm_key': '',
- 'v3_tsm_port': '10161',
'v3_users': [],
'v3_views': [],
'script_ext': {}
@@ -375,15 +366,11 @@ def get_config():
else:
snmp['v3_enabled'] = True
- #
# 'set service snmp v3 engineid'
- #
if conf.exists('v3 engineid'):
snmp['v3_engineid'] = conf.return_value('v3 engineid')
- #
# 'set service snmp v3 group'
- #
if conf.exists('v3 group'):
for group in conf.list_nodes('v3 group'):
v3_group = {
@@ -404,14 +391,11 @@ def get_config():
snmp['v3_groups'].append(v3_group)
- #
# 'set service snmp v3 trap-target'
- #
if conf.exists('v3 trap-target'):
for trap in conf.list_nodes('v3 trap-target'):
trap_cfg = {
'ipAddr': trap,
- 'engineID': '',
'secName': '',
'authProtocol': 'md5',
'authPassword': '',
@@ -425,11 +409,6 @@ def get_config():
'secLevel': 'noAuthNoPriv'
}
- if conf.exists('v3 trap-target {0} engineid'.format(trap)):
- # Set the context engineID used for SNMPv3 REQUEST messages scopedPdu.
- # If not specified, this will default to the authoritative engineID.
- trap_cfg['engineID'] = conf.return_value('v3 trap-target {0} engineid'.format(trap))
-
if conf.exists('v3 trap-target {0} user'.format(trap)):
# Set the securityName used for authenticated SNMPv3 messages.
trap_cfg['secName'] = conf.return_value('v3 trap-target {0} user'.format(trap))
@@ -483,19 +462,7 @@ def get_config():
snmp['v3_traps'].append(trap_cfg)
- #
- # 'set service snmp v3 tsm'
- #
- if conf.exists('v3 tsm'):
- if conf.exists('v3 tsm local-key'):
- snmp['v3_tsm_key'] = conf.return_value('v3 tsm local-key')
-
- if conf.exists('v3 tsm port'):
- snmp['v3_tsm_port'] = conf.return_value('v3 tsm port')
-
- #
# 'set service snmp v3 user'
- #
if conf.exists('v3 user'):
for user in conf.list_nodes('v3 user'):
user_cfg = {
@@ -504,19 +471,15 @@ def get_config():
'authPassword': '',
'authProtocol': 'md5',
'authOID': 'none',
- 'engineID': '',
'group': '',
'mode': 'ro',
'privMasterKey': '',
'privPassword': '',
'privOID': '',
- 'privTsmKey': '',
'privProtocol': 'des'
}
- #
# v3 user {0} auth
- #
if conf.exists('v3 user {0} auth encrypted-key'.format(user)):
user_cfg['authMasterKey'] = conf.return_value('v3 user {0} auth encrypted-key'.format(user))
@@ -532,36 +495,21 @@ def get_config():
user_cfg['authProtocol'] = type
user_cfg['authOID'] = OIDs[type]
- #
- # v3 user {0} engineid
- #
- if conf.exists('v3 user {0} engineid'.format(user)):
- user_cfg['engineID'] = conf.return_value('v3 user {0} engineid'.format(user))
-
- #
# v3 user {0} group
- #
if conf.exists('v3 user {0} group'.format(user)):
user_cfg['group'] = conf.return_value('v3 user {0} group'.format(user))
- #
# v3 user {0} mode
- #
if conf.exists('v3 user {0} mode'.format(user)):
user_cfg['mode'] = conf.return_value('v3 user {0} mode'.format(user))
- #
# v3 user {0} privacy
- #
if conf.exists('v3 user {0} privacy encrypted-key'.format(user)):
user_cfg['privMasterKey'] = conf.return_value('v3 user {0} privacy encrypted-key'.format(user))
if conf.exists('v3 user {0} privacy plaintext-key'.format(user)):
user_cfg['privPassword'] = conf.return_value('v3 user {0} privacy plaintext-key'.format(user))
- if conf.exists('v3 user {0} privacy tsm-key'.format(user)):
- user_cfg['privTsmKey'] = conf.return_value('v3 user {0} privacy tsm-key'.format(user))
-
# load default value
type = user_cfg['privProtocol']
if conf.exists('v3 user {0} privacy type'.format(user)):
@@ -573,9 +521,7 @@ def get_config():
snmp['v3_users'].append(user_cfg)
- #
# 'set service snmp v3 view'
- #
if conf.exists('v3 view'):
for view in conf.list_nodes('v3 view'):
view_cfg = {
@@ -601,7 +547,7 @@ def verify(snmp):
if snmp['script_ext']:
for ext in snmp['script_ext']:
if not os.path.isfile(snmp['script_ext'][ext]):
- print ("WARNING: script: " + snmp['script_ext'][ext] + " doesn\'t exist")
+ print ("WARNING: script: " + snmp['script_ext'][ext] + " doesn\'t exist")
else:
os.chmod(snmp['script_ext'][ext], 0o555)
@@ -609,14 +555,6 @@ def verify(snmp):
if not snmp['v3_enabled']:
return None
- tsmKeyPattern = re.compile('^[0-9A-F]{2}(:[0-9A-F]{2}){19}$', re.IGNORECASE)
-
- if snmp['v3_tsm_key']:
- if not tsmKeyPattern.match(snmp['v3_tsm_key']):
- if not os.path.isfile('/etc/snmp/tls/certs/' + snmp['v3_tsm_key']):
- if not os.path.isfile('/config/snmp/tls/certs/' + snmp['v3_tsm_key']):
- raise ConfigError('TSM key must be fingerprint or filename in "/config/snmp/tls/certs/" folder')
-
for listen in snmp['listen_address']:
addr = listen[0]
port = listen[1]
@@ -683,13 +621,6 @@ def verify(snmp):
if not 'privPassword' and 'privMasterKey' in trap.keys():
raise ConfigError('v3 trap: "user" must be specified')
- if 'type' in trap.keys():
- if trap['type'] == 'trap' and trap['engineID'] == '':
- raise ConfigError('must specify engineid if type is "trap"')
- else:
- raise ConfigError('"type" must be specified')
-
-
if 'v3_users' in snmp.keys():
for user in snmp['v3_users']:
#
@@ -721,21 +652,9 @@ def verify(snmp):
if user['privPassword'] == '' and user['privMasterKey'] == '':
raise ConfigError('Must specify encrypted-key or plaintext-key for user privacy')
- if user['privMasterKey'] and user['engineID'] == '':
- raise ConfigError('Can not have "encrypted-key" without engineid')
-
- if user['authPassword'] == '' and user['authMasterKey'] == '' and user['privTsmKey'] == '':
- raise ConfigError('Must specify auth or tsm-key for user auth')
-
if user['mode'] == '':
raise ConfigError('Must specify user mode ro/rw')
- if user['privTsmKey']:
- if not tsmKeyPattern.match(snmp['v3_tsm_key']):
- if not os.path.isfile('/etc/snmp/tls/certs/' + snmp['v3_tsm_key']):
- if not os.path.isfile('/config/snmp/tls/certs/' + snmp['v3_tsm_key']):
- raise ConfigError('User TSM key must be fingerprint or filename in "/config/snmp/tls/certs/" folder')
-
if 'v3_views' in snmp.keys():
for view in snmp['v3_views']:
if not view['oids']:
@@ -858,7 +777,6 @@ def apply(snmp):
# Now update the running configuration
#
# Currently when executing os.system() the environment does not have the vyos_libexec_dir variable set, see T685
- os.system('vyos_libexec_dir=/usr/libexec/vyos /opt/vyatta/sbin/my_set service snmp v3 user "{0}" engineid {1} > /dev/null'.format(cfg['user'], engineID))
os.system('vyos_libexec_dir=/usr/libexec/vyos /opt/vyatta/sbin/my_set service snmp v3 user "{0}" auth encrypted-key {1} > /dev/null'.format(cfg['user'], cfg['auth_pw']))
os.system('vyos_libexec_dir=/usr/libexec/vyos /opt/vyatta/sbin/my_set service snmp v3 user "{0}" privacy encrypted-key {1} > /dev/null'.format(cfg['user'], cfg['priv_pw']))
os.system('vyos_libexec_dir=/usr/libexec/vyos /opt/vyatta/sbin/my_delete service snmp v3 user "{0}" auth plaintext-key > /dev/null'.format(cfg['user']))
diff --git a/src/migration-scripts/snmp/0-to-1 b/src/migration-scripts/snmp/0-to-1
new file mode 100755
index 000000000..a836f7011
--- /dev/null
+++ b/src/migration-scripts/snmp/0-to-1
@@ -0,0 +1,56 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2019 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 sys
+from vyos.configtree import ConfigTree
+
+if (len(sys.argv) < 1):
+ print("Must specify file name!")
+ sys.exit(1)
+
+file_name = sys.argv[1]
+
+with open(file_name, 'r') as f:
+ config_file = f.read()
+
+config = ConfigTree(config_file)
+config_base = ['service', 'snmp', 'v3']
+
+if not config.exists(config_base):
+ # Nothing to do
+ sys.exit(0)
+else:
+ # we no longer support a per trap target engine ID (https://phabricator.vyos.net/T818)
+ if config.exists(config_base + ['v3', 'trap-target']):
+ for target in config.list_nodes(config_base + ['v3', 'trap-target']):
+ config.delete(config_base + ['v3', 'trap-target', target, 'engineid'])
+
+ # we no longer support a per user engine ID (https://phabricator.vyos.net/T818)
+ if config.exists(config_base + ['v3', 'user']):
+ for user in config.list_nodes(config_base + ['v3', 'user']):
+ config.delete(config_base + ['v3', 'user', user, 'engineid'])
+
+ # we drop TSM support as there seem to be no users and this code is untested
+ # https://phabricator.vyos.net/T1769
+ if config.exists(config_base + ['v3', 'tsm']):
+ config.delete(config_base + ['v3', 'tsm'])
+
+ try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+ except OSError as e:
+ print("Failed to save the modified config: {}".format(e))
+ sys.exit(1)