diff options
-rw-r--r-- | data/templates/snmp/etc.snmpd.conf.tmpl | 2 | ||||
-rw-r--r-- | interface-definitions/snmp.xml.in | 20 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_service_snmp.py | 47 | ||||
-rwxr-xr-x | src/conf_mode/snmp.py | 11 |
4 files changed, 75 insertions, 5 deletions
diff --git a/data/templates/snmp/etc.snmpd.conf.tmpl b/data/templates/snmp/etc.snmpd.conf.tmpl index db2114fa1..30806ce8a 100644 --- a/data/templates/snmp/etc.snmpd.conf.tmpl +++ b/data/templates/snmp/etc.snmpd.conf.tmpl @@ -39,7 +39,7 @@ SysDescr {{ description }} {% endif %} # Listen -agentaddress unix:/run/snmpd.socket{% if listen_on %}{% for li in listen_on %},{{ li }}{% endfor %}{% else %},udp:161{% if ipv6_enabled %},udp6:161{% endif %}{% endif %} +agentaddress unix:/run/snmpd.socket{% if listen_on %}{% for li in listen_on %},{{ li }}{% endfor %}{% else %},{{protocol}}:161{% if ipv6_enabled %},{{protocol}}6:161{% endif %}{% endif %} # SNMP communities {% for c in communities %} diff --git a/interface-definitions/snmp.xml.in b/interface-definitions/snmp.xml.in index 3cb736bf7..1efe5e726 100644 --- a/interface-definitions/snmp.xml.in +++ b/interface-definitions/snmp.xml.in @@ -129,6 +129,26 @@ <constraintErrorMessage>Location is limited to 255 characters or less</constraintErrorMessage> </properties> </leafNode> + <leafNode name="protocol"> + <properties> + <help>Listen protocol for SNMP</help> + <completionHelp> + <list>udp tcp</list> + </completionHelp> + <valueHelp> + <format>udp</format> + <description>Listen protocol UDP (default)</description> + </valueHelp> + <valueHelp> + <format>tcp</format> + <description>Listen protocol TCP</description> + </valueHelp> + <constraint> + <regex>^(udp|tcp)$</regex> + </constraint> + </properties> + <defaultValue>udp</defaultValue> + </leafNode> <leafNode name="smux-peer"> <properties> <help>Register a subtree for SMUX-based processing</help> diff --git a/smoketest/scripts/cli/test_service_snmp.py b/smoketest/scripts/cli/test_service_snmp.py index 00754e668..864097771 100755 --- a/smoketest/scripts/cli/test_service_snmp.py +++ b/smoketest/scripts/cli/test_service_snmp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2020 VyOS maintainers and contributors +# Copyright (C) 2019-2022 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 @@ -94,6 +94,51 @@ class TestSNMPService(VyOSUnitTestSHIM.TestCase): self.assertTrue(process_named_running(PROCESS_NAME)) self.cli_delete(['interfaces', 'dummy', dummy_if]) + def test_snmp_tcp(self): + dummy_if = 'dum123' + dummy_addr = '100.64.0.1/32' + self.cli_set(['interfaces', 'dummy', dummy_if, 'address', dummy_addr]) + + # Check if SNMP can be configured and service runs + clients = ['192.0.2.1', '2001:db8::1'] + networks = ['192.0.2.128/25', '2001:db8:babe::/48'] + listen = ['127.0.0.1', '::1', address_from_cidr(dummy_addr)] + port = '2325' + + for auth in ['ro', 'rw']: + community = 'VyOS' + auth + self.cli_set(base_path + ['community', community, 'authorization', auth]) + for client in clients: + self.cli_set(base_path + ['community', community, 'client', client]) + for network in networks: + self.cli_set(base_path + ['community', community, 'network', network]) + + for addr in listen: + self.cli_set(base_path + ['listen-address', addr, 'port', port]) + + self.cli_set(base_path + ['contact', 'maintainers@vyos.io']) + self.cli_set(base_path + ['location', 'qemu']) + self.cli_set(base_path + ['protocol', 'tcp']) + + self.cli_commit() + + # verify listen address, it will be returned as + # ['unix:/run/snmpd.socket,tcp:127.0.0.1:161,tcp6:[::1]:161'] + # thus we need to transfor this into a proper list + config = get_config_value('agentaddress') + expected = 'unix:/run/snmpd.socket' + self.assertIn(expected, config) + + for addr in listen: + if is_ipv4(addr): + expected = f'tcp:{addr}:{port}' + else: + expected = f'tcp6:[{addr}]:{port}' + self.assertIn(expected, config) + + # Check for running process + self.assertTrue(process_named_running(PROCESS_NAME)) + self.cli_delete(['interfaces', 'dummy', dummy_if]) def test_snmpv3_sha(self): # Check if SNMPv3 can be configured with SHA authentication diff --git a/src/conf_mode/snmp.py b/src/conf_mode/snmp.py index 6d22d06f1..25ff9d0dd 100755 --- a/src/conf_mode/snmp.py +++ b/src/conf_mode/snmp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2020 VyOS maintainers and contributors +# Copyright (C) 2018-2022 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 @@ -56,6 +56,7 @@ default_config_data = { 'communities': [], 'smux_peers': [], 'location' : '', + 'protocol' : 'udp', 'description' : '', 'contact' : '', 'trap_source': '', @@ -154,6 +155,9 @@ def get_config(): if conf.exists('location'): snmp['location'] = conf.return_value('location') + if conf.exists('protocol'): + snmp['protocol'] = conf.return_value('protocol') + if conf.exists('smux-peer'): snmp['smux_peers'] = conf.return_values('smux-peer') @@ -404,14 +408,15 @@ def verify(snmp): for listen in snmp['listen_address']: addr = listen[0] port = listen[1] + protocol = snmp['protocol'] tmp = None if is_ipv4(addr): # example: udp:127.0.0.1:161 - tmp = f'udp:{addr}:{port}' + tmp = f'{protocol}:{addr}:{port}' elif snmp['ipv6_enabled']: # example: udp6:[::1]:161 - tmp = f'udp6:[{addr}]:{port}' + tmp = f'{protocol}6:[{addr}]:{port}' # We only wan't to configure addresses that exist on the system. # Hint the user if they don't exist |