| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.karaf.decanter.collector.snmp; |
| |
| import org.apache.karaf.decanter.collector.utils.PropertiesPreparator; |
| import org.osgi.service.component.ComponentContext; |
| import org.osgi.service.component.annotations.*; |
| import org.osgi.service.event.Event; |
| import org.osgi.service.event.EventAdmin; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| import org.snmp4j.*; |
| import org.snmp4j.event.ResponseEvent; |
| import org.snmp4j.event.ResponseListener; |
| import org.snmp4j.mp.MPv3; |
| import org.snmp4j.mp.SnmpConstants; |
| import org.snmp4j.security.*; |
| import org.snmp4j.smi.*; |
| import org.snmp4j.transport.DefaultTcpTransportMapping; |
| import org.snmp4j.transport.DefaultUdpTransportMapping; |
| import org.snmp4j.util.DefaultPDUFactory; |
| import org.snmp4j.util.TreeEvent; |
| import org.snmp4j.util.TreeUtils; |
| |
| import java.util.Dictionary; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| @Component( |
| name = "org.apache.karaf.decanter.collector.snmp.poll", |
| immediate = true, |
| configurationPolicy = ConfigurationPolicy.REQUIRE, |
| property = { "decanter.collector.name=snmp", |
| "scheduler.period:Long=60", |
| "scheduler.concurrent:Boolean=false", |
| "scheduler.name=decanter-collector-snmp" |
| } |
| ) |
| public class SnmpPoller implements ResponseListener, Runnable { |
| |
| private final static Logger LOGGER = LoggerFactory.getLogger(SnmpPoller.class); |
| |
| @Reference |
| private EventAdmin dispatcher; |
| |
| private Dictionary<String, Object> configuration; |
| private boolean treeList; |
| private String oids; |
| |
| private Address address; |
| private TransportMapping<? extends Address> transport; |
| private Snmp snmp; |
| |
| private Target target; |
| private PDU pdu; |
| |
| @Activate |
| public void activate(ComponentContext componentContext) throws Exception { |
| activate(componentContext.getProperties()); |
| } |
| |
| public void activate(Dictionary<String, Object> configuration) throws Exception { |
| this.configuration = configuration; |
| |
| String addressConfig = (configuration.get("address") != null) ? (String) configuration.get("address") : "127.0.0.1/161"; |
| this.address = GenericAddress.parse(addressConfig); |
| |
| String protocol = (configuration.get("protocol") != null) ? (String) configuration.get("protocol") : "tcp"; |
| if (protocol.equalsIgnoreCase("tcp")) { |
| this.transport = new DefaultTcpTransportMapping(); |
| } else if (protocol.equalsIgnoreCase("udp")) { |
| this.transport = new DefaultUdpTransportMapping(); |
| } else { |
| throw new IllegalStateException("Unknown SNMP protocol: " + protocol + " (udp and tcp are supported)"); |
| } |
| int retries = (configuration.get("retries") != null) ? Integer.parseInt((String) configuration.get("retries")) : 2; |
| long timeout = (configuration.get("timeout") != null) ? Long.parseLong((String) configuration.get("timeout")) : 1500; |
| treeList = (configuration.get("treelist") != null) ? Boolean.parseBoolean((String) configuration.get("treelist")) : false; |
| oids = (configuration.get("oids") != null) ? (String) configuration.get("oids") : ""; |
| |
| this.snmp = new Snmp(transport); |
| |
| int snmpVersion = (configuration.get("snmp.version") != null) ? Integer.parseInt((String) configuration.get("snmp.version")) : SnmpConstants.version3; |
| if (snmpVersion == SnmpConstants.version3) { |
| UserTarget userTarget = new UserTarget(); |
| |
| int securityLevel = (configuration.get("security.level") != null) ? Integer.parseInt((String) configuration.get("security.level")) : SecurityLevel.AUTH_PRIV; |
| userTarget.setSecurityLevel(securityLevel); |
| String securityName = (configuration.get("security.name") != null) ? (String) configuration.get("security.name") : ""; |
| userTarget.setSecurityName(convertToOctetString(securityName)); |
| userTarget.setAddress(address); |
| userTarget.setRetries(2); |
| userTarget.setTimeout(timeout); |
| userTarget.setVersion(snmpVersion); |
| |
| this.target = userTarget; |
| |
| USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0); |
| SecurityModels.getInstance().addSecurityModel(usm); |
| |
| String authenticationProtocolConfig = (configuration.get("authentication.protocol") != null) ? (String) configuration.get("authentication.protocol") : "MD5"; |
| OID authenticationProtocol = convertAuthenticationProtocol(authenticationProtocolConfig); |
| |
| String authenticationPassphraseConfig = (configuration.get("authentication.passphrase") != null) ? (String) configuration.get("authentication.passphrase") : ""; |
| OctetString authenticationPassphrase = convertToOctetString(authenticationPassphraseConfig); |
| |
| String privacyProtocolConfig = (configuration.get("privacy.protocol") != null) ? (String) configuration.get("privacy.protocol") : "DES"; |
| OID privacyProtocol = convertPrivacyProtocol(privacyProtocolConfig); |
| |
| String privacyPassphraseConfig = (configuration.get("privacy.passphrase") != null) ? (String) configuration.get("privacy.passphrase") : ""; |
| OctetString privacyPassphrase = convertToOctetString(privacyPassphraseConfig); |
| |
| UsmUser user = new UsmUser(convertToOctetString(securityName), authenticationProtocol, |
| authenticationPassphrase, privacyProtocol, privacyPassphrase); |
| usm.addUser(convertToOctetString(securityName), user); |
| |
| ScopedPDU scopedPDU = new ScopedPDU(); |
| |
| String snmpContextEngineId = (configuration.get("snmp.context.engine.id") != null) ? (String) configuration.get("snmp.context.engine.id") : null; |
| if (snmpContextEngineId != null) { |
| scopedPDU.setContextEngineID(new OctetString(snmpContextEngineId)); |
| } |
| |
| String snmpContextName = (configuration.get("snmp.context.name") != null) ? (String) configuration.get("snmp.context.name") : null; |
| if (snmpContextName != null) { |
| scopedPDU.setContextName(new OctetString(snmpContextName)); |
| } |
| |
| this.pdu = scopedPDU; |
| } else { |
| CommunityTarget communityTarget = new CommunityTarget(); |
| String snmpCommunity = (configuration.get("snmp.community") != null) ? (String) configuration.get("snmp.community") : "public"; |
| communityTarget.setCommunity(convertToOctetString(snmpCommunity)); |
| communityTarget.setAddress(address); |
| communityTarget.setRetries(retries); |
| communityTarget.setTimeout(timeout); |
| communityTarget.setVersion(snmpVersion); |
| this.target = communityTarget; |
| this.pdu = new PDU(); |
| } |
| this.transport.listen(); |
| } |
| |
| @Deactivate |
| public void deactivate() throws Exception { |
| if (this.transport != null && this.transport.isListening()) { |
| this.transport.close(); |
| } |
| } |
| |
| @Override |
| public void run() { |
| this.pdu.clear(); |
| |
| this.pdu.setType(PDU.GETNEXT); |
| |
| if (!treeList) { |
| for (String oid : oids.split(",")) { |
| this.pdu.add(new VariableBinding(new OID(oid))); |
| } |
| } else { |
| TreeUtils treeUtils = new TreeUtils(snmp, new DefaultPDUFactory()); |
| for (String oid : oids.split(",")) { |
| List events = treeUtils.getSubtree(target, new OID(oid)); |
| for (Object event : events) { |
| TreeEvent treeEvent = (TreeEvent) event; |
| if (treeEvent == null) { |
| LOGGER.warn("SNMP event is null"); |
| continue; |
| } |
| if (treeEvent.isError()) { |
| LOGGER.error("Error in SNMP event: {}", treeEvent.getErrorMessage()); |
| continue; |
| } |
| VariableBinding[] variableBindings = treeEvent.getVariableBindings(); |
| if (variableBindings == null || variableBindings.length == 0) { |
| continue; |
| } |
| for (VariableBinding variableBinding : variableBindings) { |
| if (variableBinding == null) { |
| continue; |
| } |
| this.pdu.add(variableBinding); |
| } |
| } |
| } |
| } |
| try { |
| snmp.send(pdu, target, null, this); |
| } catch (Exception e) { |
| LOGGER.warn("Can't send SNMP request", e); |
| } |
| } |
| |
| @Override |
| public void onResponse(ResponseEvent event) { |
| ((Snmp) event.getSource()).cancel(event.getRequest(), this); |
| |
| if (event.getRequest() == null || event.getResponse() == null) { |
| return; |
| } |
| |
| PDU pdu = event.getResponse(); |
| Map<String, Object> data = new HashMap<>(); |
| data.put("type", "snmp.poll"); |
| data.put("peerAddress", event.getPeerAddress()); |
| try { |
| PropertiesPreparator.prepare(data, configuration); |
| } catch (Exception e) { |
| LOGGER.warn("Can't prepare event data", e); |
| } |
| // PDU v1 specific variables |
| if (pdu.getType() == PDU.V1TRAP) { |
| PDUv1 v1pdu = (PDUv1) pdu; |
| data.put("enterprise", v1pdu.getEnterprise().toString()); |
| data.put("agentAddress", v1pdu.getAgentAddress().toString()); |
| data.put("genericTrap", v1pdu.getGenericTrap()); |
| data.put("specificTrap", v1pdu.getSpecificTrap()); |
| data.put("timestamp", v1pdu.getTimestamp()); |
| } |
| // all variables |
| for (VariableBinding variableBinding : pdu.getVariableBindings()) { |
| data.put(variableBinding.getOid().toString(), variableBinding.getVariable().toString()); |
| } |
| // send event |
| dispatcher.postEvent(new Event("decanter/collector/snmp", data)); |
| } |
| |
| private OctetString convertToOctetString(String value) { |
| if (value == null) { |
| return null; |
| } |
| return new OctetString(value); |
| } |
| |
| private OID convertAuthenticationProtocol(String authenticationProtocol) { |
| if (authenticationProtocol == null) { |
| return null; |
| } |
| if (authenticationProtocol.equals("MD5")) { |
| return AuthMD5.ID; |
| } else if (authenticationProtocol.equals("SHA1")) { |
| return AuthSHA.ID; |
| } else { |
| throw new IllegalArgumentException("Unknown authentication protocol: " + authenticationProtocol); |
| } |
| } |
| |
| private OID convertPrivacyProtocol(String privacyProtocol) { |
| if (privacyProtocol == null) { |
| return null; |
| } |
| if (privacyProtocol.equals("DES")) { |
| return PrivDES.ID; |
| } else if (privacyProtocol.equals("TRIDES")) { |
| return Priv3DES.ID; |
| } else if (privacyProtocol.equals("AES128")) { |
| return PrivAES128.ID; |
| } else if (privacyProtocol.equals("AES192")) { |
| return PrivAES192.ID; |
| } else if (privacyProtocol.equals("AES256")) { |
| return PrivAES256.ID; |
| } else { |
| throw new IllegalArgumentException("Unknown privacy protocol: " + privacyProtocol); |
| } |
| } |
| |
| } |