Commit e52ac96c624fa2f2790d5a288683e675311e8a8a

Authored by Viacheslav Klimov
1 parent 0045f006

Implement SNMP v3 security support, remove traps support

Showing 16 changed files with 1018 additions and 247 deletions
@@ -19,6 +19,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore; @@ -19,6 +19,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
19 import lombok.Data; 19 import lombok.Data;
20 import org.apache.commons.lang3.StringUtils; 20 import org.apache.commons.lang3.StringUtils;
21 import org.thingsboard.server.common.data.DeviceTransportType; 21 import org.thingsboard.server.common.data.DeviceTransportType;
  22 +import org.thingsboard.server.common.data.transport.snmp.AuthenticationProtocol;
  23 +import org.thingsboard.server.common.data.transport.snmp.PrivacyProtocol;
22 import org.thingsboard.server.common.data.transport.snmp.SnmpProtocolVersion; 24 import org.thingsboard.server.common.data.transport.snmp.SnmpProtocolVersion;
23 25
24 @Data 26 @Data
@@ -26,9 +28,23 @@ public class SnmpDeviceTransportConfiguration implements DeviceTransportConfigur @@ -26,9 +28,23 @@ public class SnmpDeviceTransportConfiguration implements DeviceTransportConfigur
26 private String address; 28 private String address;
27 private int port; 29 private int port;
28 private SnmpProtocolVersion protocolVersion; 30 private SnmpProtocolVersion protocolVersion;
  31 +
  32 + /*
  33 + * For SNMP v1 and v2c
  34 + * */
  35 + private String community;
  36 +
  37 + /*
  38 + * For SNMP v3 with User Based Security Model
  39 + * */
  40 + private String username;
29 private String securityName; 41 private String securityName;
30 - private String authenticationPassphrase; // for SNMP v3  
31 - private String privacyPassphrase; // for SNMP v3 42 + private String contextName;
  43 + private AuthenticationProtocol authenticationProtocol;
  44 + private String authenticationPassphrase;
  45 + private PrivacyProtocol privacyProtocol;
  46 + private String privacyPassphrase;
  47 + private String engineId;
32 48
33 @Override 49 @Override
34 public DeviceTransportType getType() { 50 public DeviceTransportType getType() {
@@ -44,7 +60,6 @@ public class SnmpDeviceTransportConfiguration implements DeviceTransportConfigur @@ -44,7 +60,6 @@ public class SnmpDeviceTransportConfiguration implements DeviceTransportConfigur
44 60
45 @JsonIgnore 61 @JsonIgnore
46 private boolean isValid() { 62 private boolean isValid() {
47 - return StringUtils.isNotBlank(address) && port > 0 &&  
48 - StringUtils.isNotBlank(securityName) && protocolVersion != null; 63 + return true;
49 } 64 }
50 } 65 }
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.transport.snmp;
  17 +
  18 +import java.util.Arrays;
  19 +import java.util.Optional;
  20 +
  21 +public enum AuthenticationProtocol {
  22 + SHA_1("1.3.6.1.6.3.10.1.1.3"),
  23 + SHA_224("1.3.6.1.6.3.10.1.1.4"),
  24 + SHA_256("1.3.6.1.6.3.10.1.1.5"),
  25 + SHA_384("1.3.6.1.6.3.10.1.1.6"),
  26 + SHA_512("1.3.6.1.6.3.10.1.1.7"),
  27 + MD5("1.3.6.1.6.3.10.1.1.2");
  28 +
  29 + // oids taken from org.snmp4j.security.SecurityProtocol implementations
  30 + private final String oid;
  31 +
  32 + AuthenticationProtocol(String oid) {
  33 + this.oid = oid;
  34 + }
  35 +
  36 + public String getOid() {
  37 + return oid;
  38 + }
  39 +
  40 + public static Optional<AuthenticationProtocol> forName(String name) {
  41 + return Arrays.stream(values())
  42 + .filter(protocol -> protocol.name().equalsIgnoreCase(name))
  43 + .findFirst();
  44 + }
  45 +}
common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/PrivacyProtocol.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/configs/ClientAttributesTrapsReceivingSnmpCommunicationConfig.java
@@ -13,13 +13,31 @@ @@ -13,13 +13,31 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.common.data.transport.snmp.configs; 16 +package org.thingsboard.server.common.data.transport.snmp;
17 17
18 -import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec; 18 +import java.util.Arrays;
  19 +import java.util.Optional;
19 20
20 -public class ClientAttributesTrapsReceivingSnmpCommunicationConfig extends SnmpCommunicationConfig {  
21 - @Override  
22 - public SnmpCommunicationSpec getSpec() {  
23 - return SnmpCommunicationSpec.CLIENT_ATTRIBUTES_TRAPS_RECEIVING; 21 +public enum PrivacyProtocol {
  22 + DES("1.3.6.1.6.3.10.1.2.2"),
  23 + AES_128("1.3.6.1.6.3.10.1.2.4"),
  24 + AES_192("1.3.6.1.4.1.4976.2.2.1.1.1"),
  25 + AES_256("1.3.6.1.4.1.4976.2.2.1.1.2");
  26 +
  27 + // oids taken from org.snmp4j.security.SecurityProtocol implementations
  28 + private final String oid;
  29 +
  30 + PrivacyProtocol(String oid) {
  31 + this.oid = oid;
  32 + }
  33 +
  34 + public String getOid() {
  35 + return oid;
  36 + }
  37 +
  38 + public static Optional<PrivacyProtocol> forName(String name) {
  39 + return Arrays.stream(values())
  40 + .filter(protocol -> protocol.name().equalsIgnoreCase(name))
  41 + .findFirst();
24 } 42 }
25 } 43 }
@@ -19,10 +19,7 @@ public enum SnmpCommunicationSpec { @@ -19,10 +19,7 @@ public enum SnmpCommunicationSpec {
19 TELEMETRY_QUERYING(true), 19 TELEMETRY_QUERYING(true),
20 CLIENT_ATTRIBUTES_QUERYING(true), 20 CLIENT_ATTRIBUTES_QUERYING(true),
21 21
22 - SHARED_ATTRIBUTES_SETTING,  
23 -  
24 - TELEMETRY_TRAPS_RECEIVING,  
25 - CLIENT_ATTRIBUTES_TRAPS_RECEIVING; 22 + SHARED_ATTRIBUTES_SETTING;
26 23
27 private final boolean isRepeatingQuerying; 24 private final boolean isRepeatingQuerying;
28 25
@@ -31,9 +31,7 @@ import java.util.List; @@ -31,9 +31,7 @@ import java.util.List;
31 @JsonSubTypes({ 31 @JsonSubTypes({
32 @Type(value = TelemetryQueryingSnmpCommunicationConfig.class, name = "TELEMETRY_QUERYING"), 32 @Type(value = TelemetryQueryingSnmpCommunicationConfig.class, name = "TELEMETRY_QUERYING"),
33 @Type(value = ClientAttributesQueryingSnmpCommunicationConfig.class, name = "CLIENT_ATTRIBUTES_QUERYING"), 33 @Type(value = ClientAttributesQueryingSnmpCommunicationConfig.class, name = "CLIENT_ATTRIBUTES_QUERYING"),
34 - @Type(value = SharedAttributesSettingSnmpCommunicationConfig.class, name = "SHARED_ATTRIBUTES_SETTING"),  
35 - @Type(value = TelemetryTrapsReceivingSnmpCommunicationConfig.class, name = "TELEMETRY_TRAPS_RECEIVING"),  
36 - @Type(value = ClientAttributesTrapsReceivingSnmpCommunicationConfig.class, name = "CLIENT_ATTRIBUTES_TRAPS_RECEIVING") 34 + @Type(value = SharedAttributesSettingSnmpCommunicationConfig.class, name = "SHARED_ATTRIBUTES_SETTING")
37 }) 35 })
38 public abstract class SnmpCommunicationConfig { 36 public abstract class SnmpCommunicationConfig {
39 protected List<SnmpMapping> mappings; 37 protected List<SnmpMapping> mappings;
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.transport.snmp;
  17 +
  18 +import lombok.RequiredArgsConstructor;
  19 +import org.snmp4j.AbstractTarget;
  20 +import org.snmp4j.CommunityTarget;
  21 +import org.snmp4j.Target;
  22 +import org.snmp4j.UserTarget;
  23 +import org.snmp4j.security.SecurityLevel;
  24 +import org.snmp4j.security.SecurityModel;
  25 +import org.snmp4j.security.SecurityProtocols;
  26 +import org.snmp4j.security.USM;
  27 +import org.snmp4j.security.UsmUser;
  28 +import org.snmp4j.smi.GenericAddress;
  29 +import org.snmp4j.smi.OID;
  30 +import org.snmp4j.smi.OctetString;
  31 +import org.springframework.beans.factory.annotation.Value;
  32 +import org.springframework.stereotype.Service;
  33 +import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration;
  34 +import org.thingsboard.server.common.data.device.profile.SnmpDeviceProfileTransportConfiguration;
  35 +import org.thingsboard.server.common.data.transport.snmp.SnmpProtocolVersion;
  36 +import org.thingsboard.server.queue.util.TbSnmpTransportComponent;
  37 +import org.thingsboard.server.transport.snmp.service.SnmpTransportService;
  38 +import org.thingsboard.server.transport.snmp.session.DeviceSessionContext;
  39 +
  40 +@Service
  41 +@TbSnmpTransportComponent
  42 +@RequiredArgsConstructor
  43 +public class SnmpAuthService {
  44 + private final SnmpTransportService snmpTransportService;
  45 +
  46 + @Value("${transport.snmp.underlying_protocol}")
  47 + private String snmpUnderlyingProtocol;
  48 +
  49 + public Target setUpSnmpTarget(SnmpDeviceProfileTransportConfiguration profileTransportConfig, SnmpDeviceTransportConfiguration deviceTransportConfig) {
  50 + AbstractTarget target;
  51 +
  52 + SnmpProtocolVersion protocolVersion = deviceTransportConfig.getProtocolVersion();
  53 + switch (protocolVersion) {
  54 + case V1:
  55 + CommunityTarget communityTargetV1 = new CommunityTarget();
  56 + communityTargetV1.setSecurityModel(SecurityModel.SECURITY_MODEL_SNMPv1);
  57 + communityTargetV1.setSecurityLevel(SecurityLevel.NOAUTH_NOPRIV);
  58 + communityTargetV1.setCommunity(new OctetString(deviceTransportConfig.getCommunity()));
  59 + target = communityTargetV1;
  60 + break;
  61 + case V2C:
  62 + CommunityTarget communityTargetV2 = new CommunityTarget();
  63 + communityTargetV2.setSecurityModel(SecurityModel.SECURITY_MODEL_SNMPv2c);
  64 + communityTargetV2.setSecurityLevel(SecurityLevel.NOAUTH_NOPRIV);
  65 + communityTargetV2.setCommunity(new OctetString(deviceTransportConfig.getCommunity()));
  66 + target = communityTargetV2;
  67 + break;
  68 + case V3:
  69 + OctetString username = new OctetString(deviceTransportConfig.getUsername());
  70 + OctetString securityName = new OctetString(deviceTransportConfig.getSecurityName());
  71 + OctetString engineId = new OctetString(deviceTransportConfig.getEngineId());
  72 +
  73 + OID authenticationProtocol = new OID(deviceTransportConfig.getAuthenticationProtocol().getOid());
  74 + OID privacyProtocol = new OID(deviceTransportConfig.getPrivacyProtocol().getOid());
  75 + OctetString authenticationPassphrase = new OctetString(deviceTransportConfig.getAuthenticationPassphrase());
  76 + authenticationPassphrase = new OctetString(SecurityProtocols.getInstance().passwordToKey(authenticationProtocol, authenticationPassphrase, engineId.getValue()));
  77 + OctetString privacyPassphrase = new OctetString(deviceTransportConfig.getPrivacyPassphrase());
  78 + privacyPassphrase = new OctetString(SecurityProtocols.getInstance().passwordToKey(privacyProtocol, authenticationProtocol, privacyPassphrase, engineId.getValue()));
  79 +
  80 + USM usm = snmpTransportService.getSnmp().getUSM();
  81 + if (usm.hasUser(engineId, securityName)) {
  82 + usm.removeAllUsers(username, engineId);
  83 + }
  84 + usm.addLocalizedUser(
  85 + engineId.getValue(), username,
  86 + authenticationProtocol, authenticationPassphrase.getValue(),
  87 + privacyProtocol, privacyPassphrase.getValue()
  88 + );
  89 +
  90 + UserTarget userTarget = new UserTarget();
  91 + userTarget.setSecurityName(securityName);
  92 + userTarget.setAuthoritativeEngineID(engineId.getValue());
  93 + userTarget.setSecurityModel(SecurityModel.SECURITY_MODEL_USM);
  94 + userTarget.setSecurityLevel(SecurityLevel.AUTH_PRIV);
  95 + target = userTarget;
  96 + break;
  97 + default:
  98 + throw new UnsupportedOperationException("SNMP protocol version " + protocolVersion + " is not supported");
  99 + }
  100 +
  101 + target.setAddress(GenericAddress.parse(snmpUnderlyingProtocol + ":" + deviceTransportConfig.getAddress() + "/" + deviceTransportConfig.getPort()));
  102 + target.setTimeout(profileTransportConfig.getTimeoutMs());
  103 + target.setRetries(profileTransportConfig.getRetries());
  104 + target.setVersion(protocolVersion.getCode());
  105 +
  106 + return target;
  107 + }
  108 +
  109 + public void cleanUpSnmpAuthInfo(DeviceSessionContext sessionContext) {
  110 + SnmpDeviceTransportConfiguration deviceTransportConfiguration = sessionContext.getDeviceTransportConfiguration();
  111 + if (deviceTransportConfiguration.getProtocolVersion() == SnmpProtocolVersion.V3) {
  112 + OctetString username = new OctetString(deviceTransportConfiguration.getUsername());
  113 + OctetString engineId = new OctetString(deviceTransportConfiguration.getEngineId());
  114 + snmpTransportService.getSnmp().getUSM().removeAllUsers(username, engineId);
  115 + }
  116 + }
  117 +
  118 +}
@@ -15,9 +15,9 @@ @@ -15,9 +15,9 @@
15 */ 15 */
16 package org.thingsboard.server.transport.snmp; 16 package org.thingsboard.server.transport.snmp;
17 17
  18 +import lombok.Getter;
18 import lombok.RequiredArgsConstructor; 19 import lombok.RequiredArgsConstructor;
19 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
20 -import org.springframework.beans.factory.annotation.Value;  
21 import org.springframework.context.event.EventListener; 21 import org.springframework.context.event.EventListener;
22 import org.springframework.stereotype.Component; 22 import org.springframework.stereotype.Component;
23 import org.thingsboard.server.common.data.Device; 23 import org.thingsboard.server.common.data.Device;
@@ -61,18 +61,18 @@ import java.util.stream.Collectors; @@ -61,18 +61,18 @@ import java.util.stream.Collectors;
61 @Slf4j 61 @Slf4j
62 @RequiredArgsConstructor 62 @RequiredArgsConstructor
63 public class SnmpTransportContext extends TransportContext { 63 public class SnmpTransportContext extends TransportContext {
  64 + @Getter
64 private final SnmpTransportService snmpTransportService; 65 private final SnmpTransportService snmpTransportService;
65 private final TransportDeviceProfileCache deviceProfileCache; 66 private final TransportDeviceProfileCache deviceProfileCache;
66 private final TransportService transportService; 67 private final TransportService transportService;
67 private final ProtoTransportEntityService protoEntityService; 68 private final ProtoTransportEntityService protoEntityService;
68 private final SnmpTransportBalancingService balancingService; 69 private final SnmpTransportBalancingService balancingService;
  70 + @Getter
  71 + private final SnmpAuthService snmpAuthService;
69 72
70 private final Map<DeviceId, DeviceSessionContext> sessions = new ConcurrentHashMap<>(); 73 private final Map<DeviceId, DeviceSessionContext> sessions = new ConcurrentHashMap<>();
71 private Collection<DeviceId> allSnmpDevicesIds = new ConcurrentLinkedDeque<>(); 74 private Collection<DeviceId> allSnmpDevicesIds = new ConcurrentLinkedDeque<>();
72 75
73 - @Value("${transport.snmp.underlying_protocol}")  
74 - private String snmpUnderlyingProtocol;  
75 -  
76 @AfterStartUp(order = 2) 76 @AfterStartUp(order = 2)
77 public void initDevicesSessions() { 77 public void initDevicesSessions() {
78 log.info("Initializing SNMP devices sessions"); 78 log.info("Initializing SNMP devices sessions");
@@ -116,8 +116,7 @@ public class SnmpTransportContext extends TransportContext { @@ -116,8 +116,7 @@ public class SnmpTransportContext extends TransportContext {
116 116
117 DeviceSessionContext deviceSessionContext = new DeviceSessionContext( 117 DeviceSessionContext deviceSessionContext = new DeviceSessionContext(
118 device, deviceProfile, credentials.getCredentialsId(), 118 device, deviceProfile, credentials.getCredentialsId(),
119 - profileTransportConfiguration, deviceTransportConfiguration,  
120 - this, snmpTransportService, snmpUnderlyingProtocol 119 + profileTransportConfiguration, deviceTransportConfiguration, this
121 ); 120 );
122 registerSessionMsgListener(deviceSessionContext); 121 registerSessionMsgListener(deviceSessionContext);
123 sessions.put(device.getId(), deviceSessionContext); 122 sessions.put(device.getId(), deviceSessionContext);
@@ -155,6 +154,7 @@ public class SnmpTransportContext extends TransportContext { @@ -155,6 +154,7 @@ public class SnmpTransportContext extends TransportContext {
155 if (sessionContext == null) return; 154 if (sessionContext == null) return;
156 log.info("Destroying SNMP device session for device {}", sessionContext.getDevice().getId()); 155 log.info("Destroying SNMP device session for device {}", sessionContext.getDevice().getId());
157 sessionContext.close(); 156 sessionContext.close();
  157 + snmpAuthService.cleanUpSnmpAuthInfo(sessionContext);
158 transportService.deregisterSession(sessionContext.getSessionInfo()); 158 transportService.deregisterSession(sessionContext.getSessionInfo());
159 sessions.remove(sessionContext.getDeviceId()); 159 sessions.remove(sessionContext.getDeviceId());
160 snmpTransportService.cancelQueryingTasks(sessionContext); 160 snmpTransportService.cancelQueryingTasks(sessionContext);
@@ -19,29 +19,31 @@ import com.google.gson.JsonObject; @@ -19,29 +19,31 @@ import com.google.gson.JsonObject;
19 import lombok.Getter; 19 import lombok.Getter;
20 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
21 import org.apache.commons.lang3.StringUtils; 21 import org.apache.commons.lang3.StringUtils;
22 -import org.snmp4j.CommandResponder;  
23 -import org.snmp4j.CommandResponderEvent;  
24 import org.snmp4j.PDU; 22 import org.snmp4j.PDU;
  23 +import org.snmp4j.ScopedPDU;
25 import org.snmp4j.Snmp; 24 import org.snmp4j.Snmp;
26 import org.snmp4j.TransportMapping; 25 import org.snmp4j.TransportMapping;
27 import org.snmp4j.event.ResponseEvent; 26 import org.snmp4j.event.ResponseEvent;
  27 +import org.snmp4j.mp.MPv3;
  28 +import org.snmp4j.security.SecurityModels;
  29 +import org.snmp4j.security.SecurityProtocols;
  30 +import org.snmp4j.security.USM;
28 import org.snmp4j.smi.Null; 31 import org.snmp4j.smi.Null;
29 import org.snmp4j.smi.OID; 32 import org.snmp4j.smi.OID;
30 import org.snmp4j.smi.OctetString; 33 import org.snmp4j.smi.OctetString;
31 -import org.snmp4j.smi.TcpAddress;  
32 -import org.snmp4j.smi.UdpAddress;  
33 import org.snmp4j.smi.VariableBinding; 34 import org.snmp4j.smi.VariableBinding;
34 import org.snmp4j.transport.DefaultTcpTransportMapping; 35 import org.snmp4j.transport.DefaultTcpTransportMapping;
35 import org.snmp4j.transport.DefaultUdpTransportMapping; 36 import org.snmp4j.transport.DefaultUdpTransportMapping;
36 import org.springframework.beans.factory.annotation.Value; 37 import org.springframework.beans.factory.annotation.Value;
37 -import org.springframework.context.annotation.Lazy;  
38 import org.springframework.stereotype.Service; 38 import org.springframework.stereotype.Service;
39 import org.thingsboard.common.util.ThingsBoardThreadFactory; 39 import org.thingsboard.common.util.ThingsBoardThreadFactory;
40 import org.thingsboard.server.common.data.TbTransportService; 40 import org.thingsboard.server.common.data.TbTransportService;
  41 +import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration;
41 import org.thingsboard.server.common.data.id.DeviceProfileId; 42 import org.thingsboard.server.common.data.id.DeviceProfileId;
42 import org.thingsboard.server.common.data.kv.DataType; 43 import org.thingsboard.server.common.data.kv.DataType;
43 import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec; 44 import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec;
44 import org.thingsboard.server.common.data.transport.snmp.SnmpMapping; 45 import org.thingsboard.server.common.data.transport.snmp.SnmpMapping;
  46 +import org.thingsboard.server.common.data.transport.snmp.SnmpProtocolVersion;
45 import org.thingsboard.server.common.data.transport.snmp.configs.RepeatingQueryingSnmpCommunicationConfig; 47 import org.thingsboard.server.common.data.transport.snmp.configs.RepeatingQueryingSnmpCommunicationConfig;
46 import org.thingsboard.server.common.data.transport.snmp.configs.SnmpCommunicationConfig; 48 import org.thingsboard.server.common.data.transport.snmp.configs.SnmpCommunicationConfig;
47 import org.thingsboard.server.common.transport.TransportService; 49 import org.thingsboard.server.common.transport.TransportService;
@@ -49,12 +51,12 @@ import org.thingsboard.server.common.transport.TransportServiceCallback; @@ -49,12 +51,12 @@ import org.thingsboard.server.common.transport.TransportServiceCallback;
49 import org.thingsboard.server.common.transport.adaptor.JsonConverter; 51 import org.thingsboard.server.common.transport.adaptor.JsonConverter;
50 import org.thingsboard.server.gen.transport.TransportProtos; 52 import org.thingsboard.server.gen.transport.TransportProtos;
51 import org.thingsboard.server.queue.util.TbSnmpTransportComponent; 53 import org.thingsboard.server.queue.util.TbSnmpTransportComponent;
52 -import org.thingsboard.server.transport.snmp.SnmpTransportContext;  
53 import org.thingsboard.server.transport.snmp.session.DeviceSessionContext; 54 import org.thingsboard.server.transport.snmp.session.DeviceSessionContext;
54 55
55 import javax.annotation.PostConstruct; 56 import javax.annotation.PostConstruct;
56 import javax.annotation.PreDestroy; 57 import javax.annotation.PreDestroy;
57 import java.io.IOException; 58 import java.io.IOException;
  59 +import java.util.Collections;
58 import java.util.EnumMap; 60 import java.util.EnumMap;
59 import java.util.HashMap; 61 import java.util.HashMap;
60 import java.util.List; 62 import java.util.List;
@@ -67,13 +69,11 @@ import java.util.concurrent.ScheduledFuture; @@ -67,13 +69,11 @@ import java.util.concurrent.ScheduledFuture;
67 import java.util.concurrent.TimeUnit; 69 import java.util.concurrent.TimeUnit;
68 import java.util.function.BiConsumer; 70 import java.util.function.BiConsumer;
69 import java.util.stream.Collectors; 71 import java.util.stream.Collectors;
70 -import java.util.stream.Stream;  
71 72
72 @TbSnmpTransportComponent 73 @TbSnmpTransportComponent
73 @Service 74 @Service
74 @Slf4j 75 @Slf4j
75 -public class SnmpTransportService implements TbTransportService, CommandResponder {  
76 - private final SnmpTransportContext snmpTransportContext; 76 +public class SnmpTransportService implements TbTransportService {
77 private final TransportService transportService; 77 private final TransportService transportService;
78 78
79 @Getter 79 @Getter
@@ -88,9 +88,7 @@ public class SnmpTransportService implements TbTransportService, CommandResponde @@ -88,9 +88,7 @@ public class SnmpTransportService implements TbTransportService, CommandResponde
88 @Value("${transport.snmp.underlying_protocol}") 88 @Value("${transport.snmp.underlying_protocol}")
89 private String snmpUnderlyingProtocol; 89 private String snmpUnderlyingProtocol;
90 90
91 - public SnmpTransportService(@Lazy SnmpTransportContext snmpTransportContext,  
92 - TransportService transportService) {  
93 - this.snmpTransportContext = snmpTransportContext; 91 + public SnmpTransportService(TransportService transportService) {
94 this.transportService = transportService; 92 this.transportService = transportService;
95 } 93 }
96 94
@@ -102,7 +100,6 @@ public class SnmpTransportService implements TbTransportService, CommandResponde @@ -102,7 +100,6 @@ public class SnmpTransportService implements TbTransportService, CommandResponde
102 responseProcessingExecutor = Executors.newWorkStealingPool(responseProcessingParallelismLevel); 100 responseProcessingExecutor = Executors.newWorkStealingPool(responseProcessingParallelismLevel);
103 101
104 initializeSnmp(); 102 initializeSnmp();
105 - initializeTrapsListener();  
106 configureResponseProcessors(); 103 configureResponseProcessors();
107 104
108 log.info("SNMP transport service initialized"); 105 log.info("SNMP transport service initialized");
@@ -122,29 +119,9 @@ public class SnmpTransportService implements TbTransportService, CommandResponde @@ -122,29 +119,9 @@ public class SnmpTransportService implements TbTransportService, CommandResponde
122 } 119 }
123 snmp = new Snmp(transportMapping); 120 snmp = new Snmp(transportMapping);
124 snmp.listen(); 121 snmp.listen();
125 - }  
126 -  
127 - private void initializeTrapsListener() throws IOException {  
128 - int trapsListeningPort = 1062;  
129 - String bindingAddress = "0.0.0.0/" + trapsListeningPort;  
130 122
131 - TransportMapping<?> transportMapping;  
132 - switch (snmpUnderlyingProtocol) {  
133 - case "udp":  
134 - transportMapping = new DefaultUdpTransportMapping(new UdpAddress(bindingAddress));  
135 - break;  
136 - case "tcp":  
137 - transportMapping = new DefaultTcpTransportMapping(new TcpAddress(bindingAddress));  
138 - break;  
139 - default:  
140 - throw new IllegalArgumentException("Underlying protocol " + snmpUnderlyingProtocol + " for SNMP is not supported");  
141 - }  
142 -  
143 -  
144 - Snmp trapsSnmp = new Snmp(transportMapping);  
145 - trapsSnmp.addCommandResponder(this);  
146 -  
147 - transportMapping.listen(); 123 + USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
  124 + SecurityModels.getInstance().addSecurityModel(usm);
148 } 125 }
149 126
150 public void createQueryingTasks(DeviceSessionContext sessionContext) { 127 public void createQueryingTasks(DeviceSessionContext sessionContext) {
@@ -177,12 +154,11 @@ public class SnmpTransportService implements TbTransportService, CommandResponde @@ -177,12 +154,11 @@ public class SnmpTransportService implements TbTransportService, CommandResponde
177 } 154 }
178 155
179 public void sendRequest(DeviceSessionContext sessionContext, SnmpCommunicationConfig communicationConfig) throws IOException { 156 public void sendRequest(DeviceSessionContext sessionContext, SnmpCommunicationConfig communicationConfig) throws IOException {
180 - PDU request = createPdu(communicationConfig);  
181 - executeRequest(sessionContext, request); 157 + sendRequest(sessionContext, communicationConfig, Collections.emptyMap());
182 } 158 }
183 159
184 public void sendRequest(DeviceSessionContext sessionContext, SnmpCommunicationConfig communicationConfig, Map<String, String> values) throws IOException { 160 public void sendRequest(DeviceSessionContext sessionContext, SnmpCommunicationConfig communicationConfig, Map<String, String> values) throws IOException {
185 - PDU request = createPduWithValues(communicationConfig, values); 161 + PDU request = createPdu(sessionContext, communicationConfig, values);
186 executeRequest(sessionContext, request); 162 executeRequest(sessionContext, request);
187 } 163 }
188 164
@@ -193,46 +169,37 @@ public class SnmpTransportService implements TbTransportService, CommandResponde @@ -193,46 +169,37 @@ public class SnmpTransportService implements TbTransportService, CommandResponde
193 } 169 }
194 } 170 }
195 171
196 - private PDU createPdu(SnmpCommunicationConfig communicationConfig) {  
197 - PDU pdu = new PDU();  
198 - pdu.setType(communicationConfig.getMethod().getCode());  
199 - pdu.addAll(communicationConfig.getMappings().stream()  
200 - .map(mapping -> new VariableBinding(new OID(mapping.getOid())))  
201 - .collect(Collectors.toList()));  
202 - return pdu;  
203 - } 172 + private PDU createPdu(DeviceSessionContext sessionContext, SnmpCommunicationConfig communicationConfig, Map<String, String> values) {
  173 + PDU pdu;
  174 + SnmpDeviceTransportConfiguration deviceTransportConfiguration = sessionContext.getDeviceTransportConfiguration();
  175 + SnmpProtocolVersion snmpVersion = deviceTransportConfiguration.getProtocolVersion();
  176 + switch (snmpVersion) {
  177 + case V1:
  178 + case V2C:
  179 + pdu = new PDU();
  180 + break;
  181 + case V3:
  182 + ScopedPDU scopedPdu = new ScopedPDU();
  183 + scopedPdu.setContextName(new OctetString(deviceTransportConfiguration.getContextName()));
  184 + scopedPdu.setContextEngineID(new OctetString(deviceTransportConfiguration.getEngineId()));
  185 + pdu = scopedPdu;
  186 + break;
  187 + default:
  188 + throw new UnsupportedOperationException("SNMP version " + snmpVersion + " is not supported");
  189 + }
204 190
205 - private PDU createPduWithValues(SnmpCommunicationConfig communicationConfig, Map<String, String> values) {  
206 - PDU pdu = new PDU();  
207 pdu.setType(communicationConfig.getMethod().getCode()); 191 pdu.setType(communicationConfig.getMethod().getCode());
208 pdu.addAll(communicationConfig.getMappings().stream() 192 pdu.addAll(communicationConfig.getMappings().stream()
209 - .filter(mapping -> values.containsKey(mapping.getKey()))  
210 - .map(mapping -> {  
211 - String value = values.get(mapping.getKey());  
212 - return new VariableBinding(new OID(mapping.getOid()), new OctetString(value));  
213 - }) 193 + .filter(mapping -> values.isEmpty() || values.containsKey(mapping.getKey()))
  194 + .map(mapping -> Optional.ofNullable(values.get(mapping.getKey()))
  195 + .map(value -> new VariableBinding(new OID(mapping.getOid()), new OctetString(values.get(mapping.getKey()))))
  196 + .orElseGet(() -> new VariableBinding(new OID(mapping.getOid()))))
214 .collect(Collectors.toList())); 197 .collect(Collectors.toList()));
  198 +
215 return pdu; 199 return pdu;
216 } 200 }
217 201
218 202
219 - private void processTrap(CommandResponderEvent event) {  
220 - if (event.getPDU().getType() != PDU.TRAP) return;  
221 -  
222 - snmpTransportContext.getSessions().stream()  
223 - .filter(sessionContext -> {  
224 - // TODO: SNMP v3 support  
225 - return sessionContext.getTarget().getSecurityName().equals(OctetString.fromByteArray(event.getSecurityName())) &&  
226 - sessionContext.getTarget().getAddress().equals(event.getPeerAddress());  
227 - })  
228 - .findFirst()  
229 - .ifPresentOrElse(sessionContext -> {  
230 - responseProcessingExecutor.execute(() -> processResponse(sessionContext, event.getPDU()));  
231 - }, () -> {  
232 - log.debug("SNMP event is from unknown source: {}", event);  
233 - });  
234 - }  
235 -  
236 public void processResponseEvent(DeviceSessionContext sessionContext, ResponseEvent event) { 203 public void processResponseEvent(DeviceSessionContext sessionContext, ResponseEvent event) {
237 ((Snmp) event.getSource()).cancel(event.getRequest(), sessionContext); 204 ((Snmp) event.getSource()).cancel(event.getRequest(), sessionContext);
238 205
@@ -243,7 +210,7 @@ public class SnmpTransportService implements TbTransportService, CommandResponde @@ -243,7 +210,7 @@ public class SnmpTransportService implements TbTransportService, CommandResponde
243 210
244 PDU response = event.getResponse(); 211 PDU response = event.getResponse();
245 if (response == null) { 212 if (response == null) {
246 - log.warn("No response from SNMP device {}, requestId: {}", sessionContext.getDeviceId(), event.getRequest().getRequestID()); 213 + log.debug("No response from SNMP device {}, requestId: {}", sessionContext.getDeviceId(), event.getRequest().getRequestID());
247 return; 214 return;
248 } 215 }
249 DeviceProfileId deviceProfileId = (DeviceProfileId) event.getUserObject(); 216 DeviceProfileId deviceProfileId = (DeviceProfileId) event.getUserObject();
@@ -308,23 +275,17 @@ public class SnmpTransportService implements TbTransportService, CommandResponde @@ -308,23 +275,17 @@ public class SnmpTransportService implements TbTransportService, CommandResponde
308 } 275 }
309 276
310 private void configureResponseProcessors() { 277 private void configureResponseProcessors() {
311 - Stream.of(SnmpCommunicationSpec.TELEMETRY_QUERYING, SnmpCommunicationSpec.TELEMETRY_TRAPS_RECEIVING)  
312 - .forEach(telemetrySpec -> {  
313 - responseProcessors.put(telemetrySpec, (response, sessionContext) -> {  
314 - TransportProtos.PostTelemetryMsg postTelemetryMsg = JsonConverter.convertToTelemetryProto(response);  
315 - transportService.process(sessionContext.getSessionInfo(), postTelemetryMsg, TransportServiceCallback.EMPTY);  
316 - log.debug("Posted telemetry for device {}: {}", sessionContext.getDeviceId(), response);  
317 - });  
318 - });  
319 -  
320 - Stream.of(SnmpCommunicationSpec.CLIENT_ATTRIBUTES_QUERYING, SnmpCommunicationSpec.CLIENT_ATTRIBUTES_TRAPS_RECEIVING)  
321 - .forEach(clientAttributesSpec -> {  
322 - responseProcessors.put(clientAttributesSpec, (response, sessionContext) -> {  
323 - TransportProtos.PostAttributeMsg postAttributesMsg = JsonConverter.convertToAttributesProto(response);  
324 - transportService.process(sessionContext.getSessionInfo(), postAttributesMsg, TransportServiceCallback.EMPTY);  
325 - log.debug("Posted attributes for device {}: {}", sessionContext.getDeviceId(), response);  
326 - });  
327 - }); 278 + responseProcessors.put(SnmpCommunicationSpec.TELEMETRY_QUERYING, (response, sessionContext) -> {
  279 + TransportProtos.PostTelemetryMsg postTelemetryMsg = JsonConverter.convertToTelemetryProto(response);
  280 + transportService.process(sessionContext.getSessionInfo(), postTelemetryMsg, TransportServiceCallback.EMPTY);
  281 + log.debug("Posted telemetry for device {}: {}", sessionContext.getDeviceId(), response);
  282 + });
  283 +
  284 + responseProcessors.put(SnmpCommunicationSpec.CLIENT_ATTRIBUTES_QUERYING, (response, sessionContext) -> {
  285 + TransportProtos.PostAttributeMsg postAttributesMsg = JsonConverter.convertToAttributesProto(response);
  286 + transportService.process(sessionContext.getSessionInfo(), postAttributesMsg, TransportServiceCallback.EMPTY);
  287 + log.debug("Posted attributes for device {}: {}", sessionContext.getDeviceId(), response);
  288 + });
328 } 289 }
329 290
330 private void reportActivity(TransportProtos.SessionInfoProto sessionInfo) { 291 private void reportActivity(TransportProtos.SessionInfoProto sessionInfo) {
@@ -354,11 +315,6 @@ public class SnmpTransportService implements TbTransportService, CommandResponde @@ -354,11 +315,6 @@ public class SnmpTransportService implements TbTransportService, CommandResponde
354 } 315 }
355 316
356 @Override 317 @Override
357 - public void processPdu(CommandResponderEvent event) {  
358 - processTrap(event);  
359 - }  
360 -  
361 - @Override  
362 public String getName() { 318 public String getName() {
363 return "SNMP"; 319 return "SNMP";
364 } 320 }
@@ -18,29 +18,15 @@ package org.thingsboard.server.transport.snmp.session; @@ -18,29 +18,15 @@ package org.thingsboard.server.transport.snmp.session;
18 import lombok.Getter; 18 import lombok.Getter;
19 import lombok.Setter; 19 import lombok.Setter;
20 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
21 -import org.snmp4j.AbstractTarget;  
22 -import org.snmp4j.CommunityTarget;  
23 import org.snmp4j.Target; 21 import org.snmp4j.Target;
24 -import org.snmp4j.UserTarget;  
25 import org.snmp4j.event.ResponseEvent; 22 import org.snmp4j.event.ResponseEvent;
26 import org.snmp4j.event.ResponseListener; 23 import org.snmp4j.event.ResponseListener;
27 -import org.snmp4j.security.AuthSHA;  
28 -import org.snmp4j.security.PrivDES;  
29 -import org.snmp4j.security.SecurityLevel;  
30 -import org.snmp4j.security.SecurityModel;  
31 -import org.snmp4j.security.SecurityModels;  
32 -import org.snmp4j.security.USM;  
33 -import org.snmp4j.security.UsmUser;  
34 -import org.snmp4j.smi.GenericAddress;  
35 -import org.snmp4j.smi.OID;  
36 -import org.snmp4j.smi.OctetString;  
37 import org.thingsboard.server.common.data.Device; 24 import org.thingsboard.server.common.data.Device;
38 import org.thingsboard.server.common.data.DeviceProfile; 25 import org.thingsboard.server.common.data.DeviceProfile;
39 import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration; 26 import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration;
40 import org.thingsboard.server.common.data.device.profile.SnmpDeviceProfileTransportConfiguration; 27 import org.thingsboard.server.common.data.device.profile.SnmpDeviceProfileTransportConfiguration;
41 import org.thingsboard.server.common.data.id.DeviceId; 28 import org.thingsboard.server.common.data.id.DeviceId;
42 import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec; 29 import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec;
43 -import org.thingsboard.server.common.data.transport.snmp.SnmpProtocolVersion;  
44 import org.thingsboard.server.common.transport.SessionMsgListener; 30 import org.thingsboard.server.common.transport.SessionMsgListener;
45 import org.thingsboard.server.common.transport.adaptor.JsonConverter; 31 import org.thingsboard.server.common.transport.adaptor.JsonConverter;
46 import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext; 32 import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext;
@@ -50,6 +36,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponse @@ -50,6 +36,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponse
50 import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotificationProto; 36 import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotificationProto;
51 import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg; 37 import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg;
52 import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg; 38 import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg;
  39 +import org.thingsboard.server.transport.snmp.SnmpAuthService;
53 import org.thingsboard.server.transport.snmp.SnmpTransportContext; 40 import org.thingsboard.server.transport.snmp.SnmpTransportContext;
54 import org.thingsboard.server.transport.snmp.service.SnmpTransportService; 41 import org.thingsboard.server.transport.snmp.service.SnmpTransportService;
55 42
@@ -77,6 +64,7 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S @@ -77,6 +64,7 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S
77 64
78 private final SnmpTransportContext snmpTransportContext; 65 private final SnmpTransportContext snmpTransportContext;
79 private final SnmpTransportService snmpTransportService; 66 private final SnmpTransportService snmpTransportService;
  67 + private final SnmpAuthService snmpAuthService;
80 68
81 @Getter 69 @Getter
82 @Setter 70 @Setter
@@ -84,7 +72,6 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S @@ -84,7 +72,6 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S
84 private final AtomicInteger msgIdSeq = new AtomicInteger(0); 72 private final AtomicInteger msgIdSeq = new AtomicInteger(0);
85 @Getter 73 @Getter
86 private boolean isActive = true; 74 private boolean isActive = true;
87 - private final String snmpUnderlyingProtocol;  
88 75
89 @Getter 76 @Getter
90 @Setter 77 @Setter
@@ -93,8 +80,7 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S @@ -93,8 +80,7 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S
93 public DeviceSessionContext(Device device, DeviceProfile deviceProfile, String token, 80 public DeviceSessionContext(Device device, DeviceProfile deviceProfile, String token,
94 SnmpDeviceProfileTransportConfiguration profileTransportConfiguration, 81 SnmpDeviceProfileTransportConfiguration profileTransportConfiguration,
95 SnmpDeviceTransportConfiguration deviceTransportConfiguration, 82 SnmpDeviceTransportConfiguration deviceTransportConfiguration,
96 - SnmpTransportContext snmpTransportContext, SnmpTransportService snmpTransportService,  
97 - String snmpUnderlyingProtocol) { 83 + SnmpTransportContext snmpTransportContext) {
98 super(UUID.randomUUID()); 84 super(UUID.randomUUID());
99 super.setDeviceId(device.getId()); 85 super.setDeviceId(device.getId());
100 super.setDeviceProfile(deviceProfile); 86 super.setDeviceProfile(deviceProfile);
@@ -102,12 +88,12 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S @@ -102,12 +88,12 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S
102 88
103 this.token = token; 89 this.token = token;
104 this.snmpTransportContext = snmpTransportContext; 90 this.snmpTransportContext = snmpTransportContext;
105 - this.snmpTransportService = snmpTransportService; 91 + this.snmpTransportService = snmpTransportContext.getSnmpTransportService();
  92 + this.snmpAuthService = snmpTransportContext.getSnmpAuthService();
106 93
107 this.profileTransportConfiguration = profileTransportConfiguration; 94 this.profileTransportConfiguration = profileTransportConfiguration;
108 this.deviceTransportConfiguration = deviceTransportConfiguration; 95 this.deviceTransportConfiguration = deviceTransportConfiguration;
109 96
110 - this.snmpUnderlyingProtocol = snmpUnderlyingProtocol;  
111 initializeTarget(profileTransportConfiguration, deviceTransportConfiguration); 97 initializeTarget(profileTransportConfiguration, deviceTransportConfiguration);
112 } 98 }
113 99
@@ -133,55 +119,7 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S @@ -133,55 +119,7 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S
133 119
134 public void initializeTarget(SnmpDeviceProfileTransportConfiguration profileTransportConfig, SnmpDeviceTransportConfiguration deviceTransportConfig) { 120 public void initializeTarget(SnmpDeviceProfileTransportConfiguration profileTransportConfig, SnmpDeviceTransportConfiguration deviceTransportConfig) {
135 log.trace("Initializing target for SNMP session of device {}", device); 121 log.trace("Initializing target for SNMP session of device {}", device);
136 -  
137 - AbstractTarget target;  
138 -  
139 - SnmpProtocolVersion protocolVersion = deviceTransportConfig.getProtocolVersion();  
140 - switch (protocolVersion) {  
141 - case V1:  
142 - CommunityTarget communityTargetV1 = new CommunityTarget();  
143 - communityTargetV1.setSecurityModel(SecurityModel.SECURITY_MODEL_SNMPv1);  
144 - communityTargetV1.setSecurityLevel(SecurityLevel.NOAUTH_NOPRIV);  
145 - communityTargetV1.setCommunity(new OctetString(deviceTransportConfig.getSecurityName()));  
146 - target = communityTargetV1;  
147 - break;  
148 - case V2C:  
149 - CommunityTarget communityTargetV2 = new CommunityTarget();  
150 - communityTargetV2.setSecurityModel(SecurityModel.SECURITY_MODEL_SNMPv2c);  
151 - communityTargetV2.setSecurityLevel(SecurityLevel.NOAUTH_NOPRIV);  
152 - communityTargetV2.setCommunity(new OctetString(deviceTransportConfig.getSecurityName()));  
153 - target = communityTargetV2;  
154 - break;  
155 - case V3:  
156 - USM usm = new USM();  
157 - SecurityModels.getInstance().addSecurityModel(usm);  
158 -  
159 - OctetString securityName = new OctetString(deviceTransportConfig.getSecurityName());  
160 - OctetString authenticationPassphrase = new OctetString(deviceTransportConfig.getAuthenticationPassphrase());  
161 - OctetString privacyPassphrase = new OctetString(deviceTransportConfig.getPrivacyPassphrase());  
162 -  
163 - OID authenticationProtocol = AuthSHA.ID;  
164 - OID privacyProtocol = PrivDES.ID; // FIXME: to config  
165 -  
166 - UsmUser user = new UsmUser(securityName, authenticationProtocol, authenticationPassphrase, privacyProtocol, privacyPassphrase);  
167 - snmpTransportService.getSnmp().getUSM().addUser(user);  
168 -  
169 - UserTarget userTarget = new UserTarget();  
170 - userTarget.setSecurityName(securityName);  
171 - userTarget.setSecurityLevel(SecurityLevel.AUTH_PRIV);  
172 -  
173 - target = userTarget;  
174 - break;  
175 - default:  
176 - throw new UnsupportedOperationException("SNMP protocol version " + protocolVersion + " is not supported");  
177 - }  
178 -  
179 - target.setAddress(GenericAddress.parse(snmpUnderlyingProtocol + ":" + deviceTransportConfig.getAddress() + "/" + deviceTransportConfig.getPort()));  
180 - target.setTimeout(profileTransportConfig.getTimeoutMs());  
181 - target.setRetries(profileTransportConfig.getRetries());  
182 - target.setVersion(protocolVersion.getCode());  
183 -  
184 - this.target = target; 122 + this.target = snmpAuthService.setUpSnmpTarget(profileTransportConfig, deviceTransportConfig);
185 log.info("SNMP target initialized: {}", target); 123 log.info("SNMP target initialized: {}", target);
186 } 124 }
187 125
@@ -73,32 +73,6 @@ public class SnmpDeviceSimulatorV2 extends BaseAgent { @@ -73,32 +73,6 @@ public class SnmpDeviceSimulatorV2 extends BaseAgent {
73 } 73 }
74 } 74 }
75 75
76 - public static void main(String[] args) throws IOException {  
77 - SnmpDeviceSimulatorV2 device = new SnmpDeviceSimulatorV2(1610, "public");  
78 -  
79 - device.start();  
80 - device.setUpMappings(Map.of(  
81 - ".1.3.6.1.2.1.1.1.50", "12",  
82 - ".1.3.6.1.2.1.2.1.52", "56",  
83 - ".1.3.6.1.2.1.3.1.54", "yes",  
84 - ".1.3.6.1.2.1.7.1.58", ""  
85 - ));  
86 -  
87 -  
88 -// while (true) {  
89 -// new Scanner(System.in).nextLine();  
90 -// device.sendTrap("127.0.0.1", 1062, Map.of(".1.3.6.1.2.87.1.56", "12"));  
91 -// System.out.println("sent");  
92 -// }  
93 -  
94 -// Snmp snmp = new Snmp(device.transportMappings[0]);  
95 -// device.snmp.addCommandResponder(event -> {  
96 -// System.out.println(event);  
97 -// });  
98 -  
99 - new Scanner(System.in).nextLine();  
100 - }  
101 -  
102 76
103 private final Target target; 77 private final Target target;
104 private final Address address; 78 private final Address address;
@@ -15,38 +15,731 @@ @@ -15,38 +15,731 @@
15 */ 15 */
16 package org.thingsboard.server.transport.snmp; 16 package org.thingsboard.server.transport.snmp;
17 17
18 -import org.snmp4j.UserTarget; 18 +import org.snmp4j.MessageDispatcherImpl;
  19 +import org.snmp4j.TransportMapping;
  20 +import org.snmp4j.agent.BaseAgent;
  21 +import org.snmp4j.agent.CommandProcessor;
  22 +import org.snmp4j.agent.DuplicateRegistrationException;
  23 +import org.snmp4j.agent.MOGroup;
  24 +import org.snmp4j.agent.ManagedObject;
  25 +import org.snmp4j.agent.mo.DefaultMOMutableRow2PC;
  26 +import org.snmp4j.agent.mo.DefaultMOTable;
  27 +import org.snmp4j.agent.mo.MOAccessImpl;
  28 +import org.snmp4j.agent.mo.MOColumn;
  29 +import org.snmp4j.agent.mo.MOMutableColumn;
  30 +import org.snmp4j.agent.mo.MOMutableTableModel;
  31 +import org.snmp4j.agent.mo.MOScalar;
  32 +import org.snmp4j.agent.mo.MOTableIndex;
  33 +import org.snmp4j.agent.mo.MOTableRow;
  34 +import org.snmp4j.agent.mo.MOTableSubIndex;
  35 +import org.snmp4j.agent.mo.ext.AgentppSimulationMib;
  36 +import org.snmp4j.agent.mo.snmp.RowStatus;
  37 +import org.snmp4j.agent.mo.snmp.SnmpCommunityMIB;
  38 +import org.snmp4j.agent.mo.snmp.SnmpNotificationMIB;
  39 +import org.snmp4j.agent.mo.snmp.SnmpTargetMIB;
  40 +import org.snmp4j.agent.mo.snmp.StorageType;
  41 +import org.snmp4j.agent.mo.snmp.TransportDomains;
  42 +import org.snmp4j.agent.mo.snmp.VacmMIB;
  43 +import org.snmp4j.agent.mo.snmp4j.example.Snmp4jHeartbeatMib;
  44 +import org.snmp4j.agent.security.MutableVACM;
  45 +import org.snmp4j.mp.MPv1;
  46 +import org.snmp4j.mp.MPv2c;
  47 +import org.snmp4j.mp.MPv3;
  48 +import org.snmp4j.mp.MessageProcessingModel;
  49 +import org.snmp4j.security.AuthHMAC192SHA256;
  50 +import org.snmp4j.security.AuthMD5;
19 import org.snmp4j.security.AuthSHA; 51 import org.snmp4j.security.AuthSHA;
  52 +import org.snmp4j.security.PrivAES128;
  53 +import org.snmp4j.security.PrivAES192;
  54 +import org.snmp4j.security.PrivAES256;
20 import org.snmp4j.security.PrivDES; 55 import org.snmp4j.security.PrivDES;
21 import org.snmp4j.security.SecurityLevel; 56 import org.snmp4j.security.SecurityLevel;
  57 +import org.snmp4j.security.SecurityModel;
22 import org.snmp4j.security.SecurityModels; 58 import org.snmp4j.security.SecurityModels;
  59 +import org.snmp4j.security.SecurityProtocols;
23 import org.snmp4j.security.USM; 60 import org.snmp4j.security.USM;
24 import org.snmp4j.security.UsmUser; 61 import org.snmp4j.security.UsmUser;
  62 +import org.snmp4j.smi.Address;
  63 +import org.snmp4j.smi.Gauge32;
  64 +import org.snmp4j.smi.GenericAddress;
  65 +import org.snmp4j.smi.Integer32;
25 import org.snmp4j.smi.OID; 66 import org.snmp4j.smi.OID;
26 import org.snmp4j.smi.OctetString; 67 import org.snmp4j.smi.OctetString;
  68 +import org.snmp4j.smi.SMIConstants;
  69 +import org.snmp4j.smi.TcpAddress;
  70 +import org.snmp4j.smi.TimeTicks;
  71 +import org.snmp4j.smi.UdpAddress;
  72 +import org.snmp4j.smi.Variable;
  73 +import org.snmp4j.transport.DefaultTcpTransportMapping;
  74 +import org.snmp4j.transport.TransportMappings;
  75 +import org.snmp4j.util.ThreadPool;
27 76
  77 +import java.io.File;
28 import java.io.IOException; 78 import java.io.IOException;
  79 +import java.util.Map;
29 80
30 -public class SnmpDeviceSimulatorV3 extends SnmpDeviceSimulatorV2 {  
31 - public SnmpDeviceSimulatorV3(int port, String securityName, String authenticationPassphrase, String privacyPassphrase) throws IOException {  
32 - super(12, null);  
33 -// super(new File("conf.agent"), new File("bootCounter.agent")); 81 +/**
  82 + * The TestAgent is a sample SNMP agent implementation of all
  83 + * features (MIB implementations) provided by the SNMP4J-Agent framework.
  84 + *
  85 + * Note, for snmp4s, this code is mostly a copy from snmp4j.
  86 + * And don't remove snmp users
  87 + *
  88 + */
  89 +public class SnmpDeviceSimulatorV3 extends BaseAgent {
  90 + protected String address;
  91 + private Snmp4jHeartbeatMib heartbeatMIB;
  92 + private AgentppSimulationMib agentppSimulationMIB;
  93 +
  94 + public SnmpDeviceSimulatorV3(CommandProcessor processor) throws IOException {
  95 + super(new File("SNMP4JTestAgentBC.cfg"), new File("SNMP4JTestAgentConfig.cfg"),
  96 + processor);
  97 + agent.setWorkerPool(ThreadPool.create("RequestPool", 4));
  98 + }
  99 +
  100 + public void setUpMappings(Map<String, String> oidToResponseMappings) {
  101 + unregisterManagedObject(getSnmpv2MIB());
  102 + oidToResponseMappings.forEach((oid, response) -> {
  103 + registerManagedObject(new MOScalar<>(new OID(oid), MOAccessImpl.ACCESS_READ_WRITE, new OctetString(response)));
  104 + });
  105 + }
  106 + protected void registerManagedObject(ManagedObject mo) {
  107 + try {
  108 + server.register(mo, null);
  109 + } catch (DuplicateRegistrationException ex) {
  110 + throw new RuntimeException(ex);
  111 + }
  112 + }
  113 +
  114 + protected void unregisterManagedObject(MOGroup moGroup) {
  115 + moGroup.unregisterMOs(server, getContext(moGroup));
  116 + }
  117 +
  118 + protected void registerManagedObjects() {
  119 + try {
  120 + server.register(createStaticIfTable(), null);
  121 + server.register(createStaticIfXTable(), null);
  122 + agentppSimulationMIB.registerMOs(server, null);
  123 + heartbeatMIB.registerMOs(server, null);
  124 + } catch (DuplicateRegistrationException ex) {
  125 + ex.printStackTrace();
  126 + }
  127 + }
  128 +
  129 + protected void addNotificationTargets(SnmpTargetMIB targetMIB,
  130 + SnmpNotificationMIB notificationMIB) {
  131 + targetMIB.addDefaultTDomains();
  132 +
  133 + targetMIB.addTargetAddress(new OctetString("notificationV2c"),
  134 + TransportDomains.transportDomainUdpIpv4,
  135 + new OctetString(new UdpAddress("127.0.0.1/162").getValue()),
  136 + 200, 1,
  137 + new OctetString("notify"),
  138 + new OctetString("v2c"),
  139 + StorageType.permanent);
  140 + targetMIB.addTargetAddress(new OctetString("notificationV3"),
  141 + TransportDomains.transportDomainUdpIpv4,
  142 + new OctetString(new UdpAddress("127.0.0.1/1162").getValue()),
  143 + 200, 1,
  144 + new OctetString("notify"),
  145 + new OctetString("v3notify"),
  146 + StorageType.permanent);
  147 + targetMIB.addTargetParams(new OctetString("v2c"),
  148 + MessageProcessingModel.MPv2c,
  149 + SecurityModel.SECURITY_MODEL_SNMPv2c,
  150 + new OctetString("cpublic"),
  151 + SecurityLevel.AUTH_PRIV,
  152 + StorageType.permanent);
  153 + targetMIB.addTargetParams(new OctetString("v3notify"),
  154 + MessageProcessingModel.MPv3,
  155 + SecurityModel.SECURITY_MODEL_USM,
  156 + new OctetString("v3notify"),
  157 + SecurityLevel.NOAUTH_NOPRIV,
  158 + StorageType.permanent);
  159 + notificationMIB.addNotifyEntry(new OctetString("default"),
  160 + new OctetString("notify"),
  161 + SnmpNotificationMIB.SnmpNotifyTypeEnum.inform,
  162 + StorageType.permanent);
  163 + }
  164 + protected void addViews(VacmMIB vacm) {
  165 + vacm.addGroup(SecurityModel.SECURITY_MODEL_SNMPv1,
  166 + new OctetString("cpublic"),
  167 + new OctetString("v1v2group"),
  168 + StorageType.nonVolatile);
  169 + vacm.addGroup(SecurityModel.SECURITY_MODEL_SNMPv2c,
  170 + new OctetString("cpublic"),
  171 + new OctetString("v1v2group"),
  172 + StorageType.nonVolatile);
  173 + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
  174 + new OctetString("SHADES"),
  175 + new OctetString("v3group"),
  176 + StorageType.nonVolatile);
  177 + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
  178 + new OctetString("MD5DES"),
  179 + new OctetString("v3group"),
  180 + StorageType.nonVolatile);
  181 + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
  182 + new OctetString("TEST"),
  183 + new OctetString("v3test"),
  184 + StorageType.nonVolatile);
  185 + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
  186 + new OctetString("SHA"),
  187 + new OctetString("v3restricted"),
  188 + StorageType.nonVolatile);
  189 + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
  190 + new OctetString("SHAAES128"),
  191 + new OctetString("v3group"),
  192 + StorageType.nonVolatile);
  193 + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
  194 + new OctetString("SHAAES192"),
  195 + new OctetString("v3group"),
  196 + StorageType.nonVolatile);
  197 + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
  198 + new OctetString("SHAAES256"),
  199 + new OctetString("v3group"),
  200 + StorageType.nonVolatile);
  201 + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
  202 + new OctetString("MD5AES128"),
  203 + new OctetString("v3group"),
  204 + StorageType.nonVolatile);
  205 + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
  206 + new OctetString("MD5AES192"),
  207 + new OctetString("v3group"),
  208 + StorageType.nonVolatile);
  209 + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
  210 + new OctetString("MD5AES256"),
  211 + new OctetString("v3group"),
  212 + StorageType.nonVolatile);
  213 + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
  214 + new OctetString("aboba"),
  215 + new OctetString("v3group"),
  216 + StorageType.nonVolatile);
  217 + //============================================//
  218 + // agent5-auth-priv
  219 + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
  220 + new OctetString("agent5"),
  221 + new OctetString("v3group"),
  222 + StorageType.nonVolatile);
  223 + //===========================================//
  224 + // agent002
  225 + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
  226 + new OctetString("agent002"),
  227 + new OctetString("v3group"),
  228 + StorageType.nonVolatile);
  229 + //===========================================//
  230 + // user001-auth-no-priv
  231 + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
  232 + new OctetString("user001"),
  233 + new OctetString("group001"),
  234 + StorageType.nonVolatile);
  235 + //===========================================//
  236 +
  237 + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
  238 + new OctetString("v3notify"),
  239 + new OctetString("v3group"),
  240 + StorageType.nonVolatile);
  241 +
  242 + //===========================================//
  243 + // group auth no priv
  244 + vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
  245 + new OctetString("v3notify-auth"),
  246 + new OctetString("group001"),
  247 + StorageType.nonVolatile);
  248 + //===========================================//
  249 +
  250 +
  251 +
  252 + // my conf
  253 + vacm.addAccess(new OctetString("group001"), new OctetString("public"),
  254 + SecurityModel.SECURITY_MODEL_USM,
  255 + SecurityLevel.AUTH_NOPRIV,
  256 + MutableVACM.VACM_MATCH_EXACT,
  257 + new OctetString("fullReadView"),
  258 + new OctetString("fullWriteView"),
  259 + new OctetString("fullNotifyView"),
  260 + StorageType.nonVolatile);
  261 +
  262 + vacm.addAccess(new OctetString("v1v2group"), new OctetString("public"),
  263 + SecurityModel.SECURITY_MODEL_ANY,
  264 + SecurityLevel.NOAUTH_NOPRIV,
  265 + MutableVACM.VACM_MATCH_EXACT,
  266 + new OctetString("fullReadView"),
  267 + new OctetString("fullWriteView"),
  268 + new OctetString("fullNotifyView"),
  269 + StorageType.nonVolatile);
  270 + vacm.addAccess(new OctetString("v3group"), new OctetString(),
  271 + SecurityModel.SECURITY_MODEL_USM,
  272 + SecurityLevel.AUTH_PRIV,
  273 + MutableVACM.VACM_MATCH_EXACT,
  274 + new OctetString("fullReadView"),
  275 + new OctetString("fullWriteView"),
  276 + new OctetString("fullNotifyView"),
  277 + StorageType.nonVolatile);
  278 + vacm.addAccess(new OctetString("v3restricted"), new OctetString(),
  279 + SecurityModel.SECURITY_MODEL_USM,
  280 + SecurityLevel.NOAUTH_NOPRIV,
  281 + MutableVACM.VACM_MATCH_EXACT,
  282 + new OctetString("restrictedReadView"),
  283 + new OctetString("restrictedWriteView"),
  284 + new OctetString("restrictedNotifyView"),
  285 + StorageType.nonVolatile);
  286 + vacm.addAccess(new OctetString("v3test"), new OctetString(),
  287 + SecurityModel.SECURITY_MODEL_USM,
  288 + SecurityLevel.AUTH_PRIV,
  289 + MutableVACM.VACM_MATCH_EXACT,
  290 + new OctetString("testReadView"),
  291 + new OctetString("testWriteView"),
  292 + new OctetString("testNotifyView"),
  293 + StorageType.nonVolatile);
  294 +
  295 + vacm.addViewTreeFamily(new OctetString("fullReadView"), new OID("1.3"),
  296 + new OctetString(), VacmMIB.vacmViewIncluded,
  297 + StorageType.nonVolatile);
  298 + vacm.addViewTreeFamily(new OctetString("fullWriteView"), new OID("1.3"),
  299 + new OctetString(), VacmMIB.vacmViewIncluded,
  300 + StorageType.nonVolatile);
  301 + vacm.addViewTreeFamily(new OctetString("fullNotifyView"), new OID("1.3"),
  302 + new OctetString(), VacmMIB.vacmViewIncluded,
  303 + StorageType.nonVolatile);
  304 +
  305 + vacm.addViewTreeFamily(new OctetString("restrictedReadView"),
  306 + new OID("1.3.6.1.2"),
  307 + new OctetString(), VacmMIB.vacmViewIncluded,
  308 + StorageType.nonVolatile);
  309 + vacm.addViewTreeFamily(new OctetString("restrictedWriteView"),
  310 + new OID("1.3.6.1.2.1"),
  311 + new OctetString(),
  312 + VacmMIB.vacmViewIncluded,
  313 + StorageType.nonVolatile);
  314 + vacm.addViewTreeFamily(new OctetString("restrictedNotifyView"),
  315 + new OID("1.3.6.1.2"),
  316 + new OctetString(), VacmMIB.vacmViewIncluded,
  317 + StorageType.nonVolatile);
  318 + vacm.addViewTreeFamily(new OctetString("restrictedNotifyView"),
  319 + new OID("1.3.6.1.6.3.1"),
  320 + new OctetString(), VacmMIB.vacmViewIncluded,
  321 + StorageType.nonVolatile);
34 322
35 - USM usm = new USM();  
36 - SecurityModels.getInstance().addSecurityModel(usm); 323 + vacm.addViewTreeFamily(new OctetString("testReadView"),
  324 + new OID("1.3.6.1.2"),
  325 + new OctetString(), VacmMIB.vacmViewIncluded,
  326 + StorageType.nonVolatile);
  327 + vacm.addViewTreeFamily(new OctetString("testReadView"),
  328 + new OID("1.3.6.1.2.1.1"),
  329 + new OctetString(), VacmMIB.vacmViewExcluded,
  330 + StorageType.nonVolatile);
  331 + vacm.addViewTreeFamily(new OctetString("testWriteView"),
  332 + new OID("1.3.6.1.2.1"),
  333 + new OctetString(),
  334 + VacmMIB.vacmViewIncluded,
  335 + StorageType.nonVolatile);
  336 + vacm.addViewTreeFamily(new OctetString("testNotifyView"),
  337 + new OID("1.3.6.1.2"),
  338 + new OctetString(), VacmMIB.vacmViewIncluded,
  339 + StorageType.nonVolatile);
37 340
  341 + }
  342 +
  343 + protected void addUsmUser(USM usm) {
  344 + UsmUser user = new UsmUser(new OctetString("SHADES"),
  345 + AuthSHA.ID,
  346 + new OctetString("SHADESAuthPassword"),
  347 + PrivDES.ID,
  348 + new OctetString("SHADESPrivPassword"));
  349 +// usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user);
  350 + usm.addUser(user.getSecurityName(), null, user);
  351 + user = new UsmUser(new OctetString("TEST"),
  352 + AuthSHA.ID,
  353 + new OctetString("maplesyrup"),
  354 + PrivDES.ID,
  355 + new OctetString("maplesyrup"));
  356 + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user);
  357 + user = new UsmUser(new OctetString("SHA"),
  358 + AuthSHA.ID,
  359 + new OctetString("SHAAuthPassword"),
  360 + null,
  361 + null);
  362 + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user);
  363 + user = new UsmUser(new OctetString("SHADES"),
  364 + AuthSHA.ID,
  365 + new OctetString("SHADESAuthPassword"),
  366 + PrivDES.ID,
  367 + new OctetString("SHADESPrivPassword"));
  368 + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user);
  369 + user = new UsmUser(new OctetString("MD5DES"),
  370 + AuthMD5.ID,
  371 + new OctetString("MD5DESAuthPassword"),
  372 + PrivDES.ID,
  373 + new OctetString("MD5DESPrivPassword"));
  374 + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user);
  375 + user = new UsmUser(new OctetString("SHAAES128"),
  376 + AuthSHA.ID,
  377 + new OctetString("SHAAES128AuthPassword"),
  378 + PrivAES128.ID,
  379 + new OctetString("SHAAES128PrivPassword"));
  380 + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user);
  381 + user = new UsmUser(new OctetString("SHAAES192"),
  382 + AuthSHA.ID,
  383 + new OctetString("SHAAES192AuthPassword"),
  384 + PrivAES192.ID,
  385 + new OctetString("SHAAES192PrivPassword"));
  386 + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user);
  387 + user = new UsmUser(new OctetString("SHAAES256"),
  388 + AuthSHA.ID,
  389 + new OctetString("SHAAES256AuthPassword"),
  390 + PrivAES256.ID,
  391 + new OctetString("SHAAES256PrivPassword"));
  392 + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user);
  393 +
  394 + user = new UsmUser(new OctetString("MD5AES128"),
  395 + AuthMD5.ID,
  396 + new OctetString("MD5AES128AuthPassword"),
  397 + PrivAES128.ID,
  398 + new OctetString("MD5AES128PrivPassword"));
  399 + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user);
  400 + user = new UsmUser(new OctetString("MD5AES192"),
  401 + AuthHMAC192SHA256.ID,
  402 + new OctetString("MD5AES192AuthPassword"),
  403 + PrivAES192.ID,
  404 + new OctetString("MD5AES192PrivPassword"));
  405 + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user);
  406 + //==============================================================
  407 + user = new UsmUser(new OctetString("MD5AES256"),
  408 + AuthMD5.ID,
  409 + new OctetString("MD5AES256AuthPassword"),
  410 + PrivAES256.ID,
  411 + new OctetString("MD5AES256PrivPassword"));
  412 + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user);
  413 + user = new UsmUser(new OctetString("MD5AES256"),
  414 + AuthMD5.ID,
  415 + new OctetString("MD5AES256AuthPassword"),
  416 + PrivAES256.ID,
  417 + new OctetString("MD5AES256PrivPassword"));
  418 + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user);
  419 +
  420 + OctetString securityName = new OctetString("aboba");
  421 + OctetString authenticationPassphrase = new OctetString("abobaaboba");
  422 + OctetString privacyPassphrase = new OctetString("abobaaboba");
38 OID authenticationProtocol = AuthSHA.ID; 423 OID authenticationProtocol = AuthSHA.ID;
39 - OID privacyProtocol = PrivDES.ID; 424 + OID privacyProtocol = PrivDES.ID; // FIXME: to config
  425 + user = new UsmUser(securityName, authenticationProtocol, authenticationPassphrase, privacyProtocol, privacyPassphrase);
  426 + usm.addUser(user);
  427 +
  428 + //===============================================================//
  429 + user = new UsmUser(new OctetString("agent5"),
  430 + AuthSHA.ID,
  431 + new OctetString("authpass"),
  432 + PrivDES.ID,
  433 + new OctetString("privpass"));
  434 + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user);
  435 + //===============================================================//
  436 + // user001
  437 + user = new UsmUser(new OctetString("user001"),
  438 + AuthSHA.ID,
  439 + new OctetString("authpass"),
  440 + null, null);
  441 + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user);
  442 + //===============================================================//
  443 + // user002
  444 + user = new UsmUser(new OctetString("user001"),
  445 + null,
  446 + null,
  447 + null, null);
  448 + usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user);
  449 + //===============================================================//
  450 +
  451 + user = new UsmUser(new OctetString("v3notify"),
  452 + null,
  453 + null,
  454 + null,
  455 + null);
  456 + usm.addUser(user.getSecurityName(), null, user);
  457 +
  458 + this.usm = usm;
  459 + }
  460 +
  461 + private static DefaultMOTable createStaticIfXTable() {
  462 + MOTableSubIndex[] subIndexes =
  463 + new MOTableSubIndex[] { new MOTableSubIndex(SMIConstants.SYNTAX_INTEGER) };
  464 + MOTableIndex indexDef = new MOTableIndex(subIndexes, false);
  465 + MOColumn[] columns = new MOColumn[19];
  466 + int c = 0;
  467 + columns[c++] =
  468 + new MOColumn(c, SMIConstants.SYNTAX_OCTET_STRING,
  469 + MOAccessImpl.ACCESS_READ_ONLY); // ifName
  470 + columns[c++] =
  471 + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32,
  472 + MOAccessImpl.ACCESS_READ_ONLY); // ifInMulticastPkts
  473 + columns[c++] =
  474 + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32,
  475 + MOAccessImpl.ACCESS_READ_ONLY); // ifInBroadcastPkts
  476 + columns[c++] =
  477 + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32,
  478 + MOAccessImpl.ACCESS_READ_ONLY); // ifOutMulticastPkts
  479 + columns[c++] =
  480 + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32,
  481 + MOAccessImpl.ACCESS_READ_ONLY); // ifOutBroadcastPkts
  482 + columns[c++] =
  483 + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32,
  484 + MOAccessImpl.ACCESS_READ_ONLY); // ifHCInOctets
  485 + columns[c++] =
  486 + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32,
  487 + MOAccessImpl.ACCESS_READ_ONLY); // ifHCInUcastPkts
  488 + columns[c++] =
  489 + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32,
  490 + MOAccessImpl.ACCESS_READ_ONLY); // ifHCInMulticastPkts
  491 + columns[c++] =
  492 + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32,
  493 + MOAccessImpl.ACCESS_READ_ONLY); // ifHCInBroadcastPkts
  494 + columns[c++] =
  495 + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32,
  496 + MOAccessImpl.ACCESS_READ_ONLY); // ifHCOutOctets
  497 + columns[c++] =
  498 + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32,
  499 + MOAccessImpl.ACCESS_READ_ONLY); // ifHCOutUcastPkts
  500 + columns[c++] =
  501 + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32,
  502 + MOAccessImpl.ACCESS_READ_ONLY); // ifHCOutMulticastPkts
  503 + columns[c++] =
  504 + new MOColumn(c, SMIConstants.SYNTAX_COUNTER32,
  505 + MOAccessImpl.ACCESS_READ_ONLY); // ifHCOutBroadcastPkts
  506 + columns[c++] =
  507 + new MOColumn(c, SMIConstants.SYNTAX_INTEGER,
  508 + MOAccessImpl.ACCESS_READ_WRITE); // ifLinkUpDownTrapEnable
  509 + columns[c++] =
  510 + new MOColumn(c, SMIConstants.SYNTAX_GAUGE32,
  511 + MOAccessImpl.ACCESS_READ_ONLY); // ifHighSpeed
  512 + columns[c++] =
  513 + new MOColumn(c, SMIConstants.SYNTAX_INTEGER,
  514 + MOAccessImpl.ACCESS_READ_WRITE); // ifPromiscuousMode
  515 + columns[c++] =
  516 + new MOColumn(c, SMIConstants.SYNTAX_INTEGER,
  517 + MOAccessImpl.ACCESS_READ_ONLY); // ifConnectorPresent
  518 + columns[c++] =
  519 + new MOMutableColumn(c, SMIConstants.SYNTAX_OCTET_STRING, // ifAlias
  520 + MOAccessImpl.ACCESS_READ_WRITE, null);
  521 + columns[c++] =
  522 + new MOColumn(c, SMIConstants.SYNTAX_TIMETICKS,
  523 + MOAccessImpl.ACCESS_READ_ONLY); // ifCounterDiscontinuityTime
  524 +
  525 + DefaultMOTable ifXTable =
  526 + new DefaultMOTable(new OID("1.3.6.1.2.1.31.1.1.1"), indexDef, columns);
  527 + MOMutableTableModel model = (MOMutableTableModel) ifXTable.getModel();
  528 + Variable[] rowValues1 = new Variable[] {
  529 + new OctetString("Ethernet-0"),
  530 + new Integer32(1),
  531 + new Integer32(2),
  532 + new Integer32(3),
  533 + new Integer32(4),
  534 + new Integer32(5),
  535 + new Integer32(6),
  536 + new Integer32(7),
  537 + new Integer32(8),
  538 + new Integer32(9),
  539 + new Integer32(10),
  540 + new Integer32(11),
  541 + new Integer32(12),
  542 + new Integer32(13),
  543 + new Integer32(14),
  544 + new Integer32(15),
  545 + new Integer32(16),
  546 + new OctetString("My eth"),
  547 + new TimeTicks(1000)
  548 + };
  549 + Variable[] rowValues2 = new Variable[] {
  550 + new OctetString("Loopback"),
  551 + new Integer32(21),
  552 + new Integer32(22),
  553 + new Integer32(23),
  554 + new Integer32(24),
  555 + new Integer32(25),
  556 + new Integer32(26),
  557 + new Integer32(27),
  558 + new Integer32(28),
  559 + new Integer32(29),
  560 + new Integer32(30),
  561 + new Integer32(31),
  562 + new Integer32(32),
  563 + new Integer32(33),
  564 + new Integer32(34),
  565 + new Integer32(35),
  566 + new Integer32(36),
  567 + new OctetString("My loop"),
  568 + new TimeTicks(2000)
  569 + };
  570 + model.addRow(new DefaultMOMutableRow2PC(new OID("1"), rowValues1));
  571 + model.addRow(new DefaultMOMutableRow2PC(new OID("2"), rowValues2));
  572 + ifXTable.setVolatile(true);
  573 + return ifXTable;
  574 + }
  575 +
  576 + private static DefaultMOTable createStaticIfTable() {
  577 + MOTableSubIndex[] subIndexes =
  578 + new MOTableSubIndex[] { new MOTableSubIndex(SMIConstants.SYNTAX_INTEGER) };
  579 + MOTableIndex indexDef = new MOTableIndex(subIndexes, false);
  580 + MOColumn[] columns = new MOColumn[8];
  581 + int c = 0;
  582 + columns[c++] =
  583 + new MOColumn(c, SMIConstants.SYNTAX_INTEGER,
  584 + MOAccessImpl.ACCESS_READ_ONLY); // ifIndex
  585 + columns[c++] =
  586 + new MOColumn(c, SMIConstants.SYNTAX_OCTET_STRING,
  587 + MOAccessImpl.ACCESS_READ_ONLY); // ifDescr
  588 + columns[c++] =
  589 + new MOColumn(c, SMIConstants.SYNTAX_INTEGER,
  590 + MOAccessImpl.ACCESS_READ_ONLY); // ifType
  591 + columns[c++] =
  592 + new MOColumn(c, SMIConstants.SYNTAX_INTEGER,
  593 + MOAccessImpl.ACCESS_READ_ONLY); // ifMtu
  594 + columns[c++] =
  595 + new MOColumn(c, SMIConstants.SYNTAX_GAUGE32,
  596 + MOAccessImpl.ACCESS_READ_ONLY); // ifSpeed
  597 + columns[c++] =
  598 + new MOColumn(c, SMIConstants.SYNTAX_OCTET_STRING,
  599 + MOAccessImpl.ACCESS_READ_ONLY); // ifPhysAddress
  600 + columns[c++] =
  601 + new MOMutableColumn(c, SMIConstants.SYNTAX_INTEGER, // ifAdminStatus
  602 + MOAccessImpl.ACCESS_READ_WRITE, null);
  603 + columns[c++] =
  604 + new MOColumn(c, SMIConstants.SYNTAX_INTEGER,
  605 + MOAccessImpl.ACCESS_READ_ONLY); // ifOperStatus
40 606
41 - UsmUser user = new UsmUser(new OctetString(securityName), authenticationProtocol, new OctetString(authenticationPassphrase), privacyProtocol, new OctetString(privacyPassphrase)); 607 + DefaultMOTable ifTable =
  608 + new DefaultMOTable(new OID("1.3.6.1.2.1.2.2.1"), indexDef, columns);
  609 + MOMutableTableModel model = (MOMutableTableModel) ifTable.getModel();
  610 + Variable[] rowValues1 = new Variable[] {
  611 + new Integer32(1),
  612 + new OctetString("eth0"),
  613 + new Integer32(6),
  614 + new Integer32(1500),
  615 + new Gauge32(100000000),
  616 + new OctetString("00:00:00:00:01"),
  617 + new Integer32(1),
  618 + new Integer32(1)
  619 + };
  620 + Variable[] rowValues2 = new Variable[] {
  621 + new Integer32(2),
  622 + new OctetString("loopback"),
  623 + new Integer32(24),
  624 + new Integer32(1500),
  625 + new Gauge32(10000000),
  626 + new OctetString("00:00:00:00:02"),
  627 + new Integer32(1),
  628 + new Integer32(1)
  629 + };
  630 + model.addRow(new DefaultMOMutableRow2PC(new OID("1"), rowValues1));
  631 + model.addRow(new DefaultMOMutableRow2PC(new OID("2"), rowValues2));
  632 + ifTable.setVolatile(true);
  633 + return ifTable;
42 } 634 }
43 635
44 - public void initV3(UsmUser user, String securityName) {  
45 -// snmp.getUSM().addUser(user); 636 + private static DefaultMOTable createStaticSnmp4sTable() {
  637 + MOTableSubIndex[] subIndexes =
  638 + new MOTableSubIndex[] { new MOTableSubIndex(SMIConstants.SYNTAX_INTEGER) };
  639 + MOTableIndex indexDef = new MOTableIndex(subIndexes, false);
  640 + MOColumn[] columns = new MOColumn[8];
  641 + int c = 0;
  642 + columns[c++] = new MOColumn(c, SMIConstants.SYNTAX_NULL, MOAccessImpl.ACCESS_READ_ONLY); // testNull
  643 + columns[c++] = new MOColumn(c, SMIConstants.SYNTAX_INTEGER, MOAccessImpl.ACCESS_READ_ONLY); // testBoolean
  644 + columns[c++] = new MOColumn(c, SMIConstants.SYNTAX_INTEGER, MOAccessImpl.ACCESS_READ_ONLY); // ifType
  645 + columns[c++] = new MOColumn(c, SMIConstants.SYNTAX_INTEGER, MOAccessImpl.ACCESS_READ_ONLY); // ifMtu
  646 + columns[c++] = new MOColumn(c, SMIConstants.SYNTAX_GAUGE32, MOAccessImpl.ACCESS_READ_ONLY); // ifSpeed
  647 + columns[c++] = new MOColumn(c, SMIConstants.SYNTAX_OCTET_STRING, MOAccessImpl.ACCESS_READ_ONLY); //ifPhysAddress
  648 + columns[c++] = new MOMutableColumn(c, SMIConstants.SYNTAX_INTEGER, MOAccessImpl.ACCESS_READ_WRITE,
  649 + null);
  650 + // ifAdminStatus
  651 + columns[c++] = new MOColumn(c, SMIConstants.SYNTAX_INTEGER, MOAccessImpl.ACCESS_READ_ONLY);
  652 + // ifOperStatus
  653 +
  654 + DefaultMOTable ifTable =
  655 + new DefaultMOTable(new OID("1.3.6.1.4.1.50000.1.1"), indexDef, columns);
  656 + MOMutableTableModel model = (MOMutableTableModel) ifTable.getModel();
  657 + Variable[] rowValues1 = new Variable[] {
  658 + new Integer32(1),
  659 + new OctetString("eth0"),
  660 + new Integer32(6),
  661 + new Integer32(1500),
  662 + new Gauge32(100000000),
  663 + new OctetString("00:00:00:00:01"),
  664 + new Integer32(1),
  665 + new Integer32(1)
  666 + };
  667 + Variable[] rowValues2 = new Variable[] {
  668 + new Integer32(2),
  669 + new OctetString("loopback"),
  670 + new Integer32(24),
  671 + new Integer32(1500),
  672 + new Gauge32(10000000),
  673 + new OctetString("00:00:00:00:02"),
  674 + new Integer32(1),
  675 + new Integer32(1)
  676 + };
  677 + model.addRow(new DefaultMOMutableRow2PC(new OID("1"), rowValues1));
  678 + model.addRow(new DefaultMOMutableRow2PC(new OID("2"), rowValues2));
  679 + ifTable.setVolatile(true);
  680 + return ifTable;
  681 + }
  682 +
  683 + protected void initTransportMappings() throws IOException {
  684 + transportMappings = new TransportMapping[2];
  685 + Address addr = GenericAddress.parse(address);
  686 + TransportMapping tm =
  687 + TransportMappings.getInstance().createTransportMapping(addr);
  688 + transportMappings[0] = tm;
  689 + transportMappings[1] = new DefaultTcpTransportMapping(new TcpAddress(address));
  690 + }
  691 +
  692 + public void start(String ip, String port) throws IOException {
  693 + address = ip + "/" + port;
  694 + //BasicConfigurator.configure();
  695 + init();
  696 + addShutdownHook();
  697 +// loadConfig(ImportModes.REPLACE_CREATE);
  698 + getServer().addContext(new OctetString("public"));
  699 + finishInit();
  700 + run();
  701 + sendColdStartNotification();
  702 + }
  703 +
  704 + protected void unregisterManagedObjects() {
  705 + // here we should unregister those objects previously registered...
  706 + }
  707 +
  708 + protected void addCommunities(SnmpCommunityMIB communityMIB) {
  709 + Variable[] com2sec = new Variable[] {
  710 + new OctetString("public"), // community name
  711 + new OctetString("cpublic"), // security name
  712 + getAgent().getContextEngineID(), // local engine ID
  713 + new OctetString("public"), // default context name
  714 + new OctetString(), // transport tag
  715 + new Integer32(StorageType.nonVolatile), // storage type
  716 + new Integer32(RowStatus.active) // row status
  717 + };
  718 + MOTableRow row =
  719 + communityMIB.getSnmpCommunityEntry().createRow(
  720 + new OctetString("public2public").toSubIndex(true), com2sec);
  721 + communityMIB.getSnmpCommunityEntry().addRow((SnmpCommunityMIB.SnmpCommunityEntryRow) row);
  722 +// snmpCommunityMIB.setSourceAddressFiltering(true);
  723 + }
  724 +
  725 + protected void registerSnmpMIBs() {
  726 + heartbeatMIB = new Snmp4jHeartbeatMib(super.getNotificationOriginator(),
  727 + new OctetString(),
  728 + super.snmpv2MIB.getSysUpTime());
  729 + agentppSimulationMIB = new AgentppSimulationMib();
  730 + super.registerSnmpMIBs();
  731 + }
46 732
47 - UserTarget userTarget = new UserTarget();  
48 - userTarget.setSecurityName(new OctetString(securityName));  
49 - userTarget.setSecurityLevel(SecurityLevel.AUTH_PRIV); 733 + protected void initMessageDispatcher() {
  734 + this.dispatcher = new MessageDispatcherImpl();
  735 + this.mpv3 = new MPv3(this.agent.getContextEngineID().getValue());
  736 + this.usm = new USM(SecurityProtocols.getInstance(), this.agent.getContextEngineID(), this.updateEngineBoots());
  737 + SecurityModels.getInstance().addSecurityModel(this.usm);
  738 + SecurityProtocols.getInstance().addDefaultProtocols();
  739 + this.dispatcher.addMessageProcessingModel(new MPv1());
  740 + this.dispatcher.addMessageProcessingModel(new MPv2c());
  741 + this.dispatcher.addMessageProcessingModel(this.mpv3);
  742 + this.initSnmpSession();
50 } 743 }
51 744
52 -} 745 +}
common/transport/snmp/src/test/java/org/thingsboard/server/transport/snmp/SnmpTestV2.java renamed from common/transport/snmp/src/test/java/org/thingsboard/server/transport/snmp/SnmpTest.java
@@ -19,7 +19,7 @@ import java.io.IOException; @@ -19,7 +19,7 @@ import java.io.IOException;
19 import java.util.Map; 19 import java.util.Map;
20 import java.util.Scanner; 20 import java.util.Scanner;
21 21
22 -public class SnmpTest { 22 +public class SnmpTestV2 {
23 public static void main(String[] args) throws IOException { 23 public static void main(String[] args) throws IOException {
24 SnmpDeviceSimulatorV2 device = new SnmpDeviceSimulatorV2(1610, "public"); 24 SnmpDeviceSimulatorV2 device = new SnmpDeviceSimulatorV2(1610, "public");
25 25
common/transport/snmp/src/test/java/org/thingsboard/server/transport/snmp/SnmpTestV3.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/configs/TelemetryTrapsReceivingSnmpCommunicationConfig.java
@@ -13,18 +13,34 @@ @@ -13,18 +13,34 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.common.data.transport.snmp.configs; 16 +package org.thingsboard.server.transport.snmp;
17 17
18 -import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec; 18 +import org.snmp4j.CommandResponderEvent;
  19 +import org.snmp4j.agent.CommandProcessor;
  20 +import org.snmp4j.mp.MPv3;
  21 +import org.snmp4j.smi.OctetString;
19 22
20 -public class TelemetryTrapsReceivingSnmpCommunicationConfig extends SnmpCommunicationConfig {  
21 - @Override  
22 - public SnmpCommunicationSpec getSpec() {  
23 - return SnmpCommunicationSpec.TELEMETRY_TRAPS_RECEIVING;  
24 - } 23 +import java.io.IOException;
  24 +import java.util.Map;
  25 +import java.util.Scanner;
  26 +
  27 +public class SnmpTestV3 {
  28 + public static void main(String[] args) throws IOException {
  29 + SnmpDeviceSimulatorV3 device = new SnmpDeviceSimulatorV3(new CommandProcessor(new OctetString(MPv3.createLocalEngineID())) {
  30 + @Override
  31 + public void processPdu(CommandResponderEvent event) {
  32 + System.out.println("event: " + event);
  33 + }
  34 + });
  35 + device.start("0.0.0.0", "1610");
  36 +
  37 + device.setUpMappings(Map.of(
  38 + ".1.3.6.1.2.1.1.1.50", "12",
  39 + ".1.3.6.1.2.1.2.1.52", "56",
  40 + ".1.3.6.1.2.1.3.1.54", "yes",
  41 + ".1.3.6.1.2.1.7.1.58", ""
  42 + ));
25 43
26 - @Override  
27 - public boolean isValid() {  
28 - return false; 44 + new Scanner(System.in).nextLine();
29 } 45 }
30 } 46 }
@@ -38,16 +38,6 @@ @@ -38,16 +38,6 @@
38 "dataType": "STRING" 38 "dataType": "STRING"
39 } 39 }
40 ] 40 ]
41 - },  
42 - {  
43 - "spec": "TELEMETRY_TRAPS_RECEIVING",  
44 - "mappings": [  
45 - {  
46 - "oid": ".1.3.6.1.2.8.7.1.56",  
47 - "key": "temperature_trap",  
48 - "dataType": "LONG"  
49 - }  
50 - ]  
51 } 41 }
52 ] 42 ]
53 } 43 }
  1 +{
  2 + "address": "192.168.3.23",
  3 + "port": 1610,
  4 + "protocolVersion": "V3",
  5 +
  6 + "username": "tb-user",
  7 + "engineId": "qwertyuioa",
  8 + "securityName": "tb-user",
  9 + "authenticationProtocol": "SHA_512",
  10 + "authenticationPassphrase": "sdfghjkloifgh",
  11 + "privacyProtocol": "DES",
  12 + "privacyPassphrase": "rtytguijokod"
  13 +}
1 { 1 {
2 "address": "127.0.0.1", 2 "address": "127.0.0.1",
3 "port": 1610, 3 "port": 1610,
4 - "password": "public", 4 + "community": "public",
5 "protocolVersion": "V2C" 5 "protocolVersion": "V2C"
6 } 6 }