View Javadoc

1   package net.sf.snmpadaptor4j.api.opennms;
2   
3   import java.net.InetAddress;
4   import java.util.Map.Entry;
5   import org.opennms.protocols.snmp.SnmpHandler;
6   import org.opennms.protocols.snmp.SnmpIPAddress;
7   import org.opennms.protocols.snmp.SnmpObjectId;
8   import org.opennms.protocols.snmp.SnmpParameters;
9   import org.opennms.protocols.snmp.SnmpPduPacket;
10  import org.opennms.protocols.snmp.SnmpPduRequest;
11  import org.opennms.protocols.snmp.SnmpPduTrap;
12  import org.opennms.protocols.snmp.SnmpPeer;
13  import org.opennms.protocols.snmp.SnmpSMI;
14  import org.opennms.protocols.snmp.SnmpSession;
15  import org.opennms.protocols.snmp.SnmpSyntax;
16  import org.opennms.protocols.snmp.SnmpVarBind;
17  import net.sf.snmpadaptor4j.api.SnmpTrapSender;
18  import net.sf.snmpadaptor4j.object.SnmpDataType;
19  import net.sf.snmpadaptor4j.object.SnmpOid;
20  import net.sf.snmpadaptor4j.object.SnmpTrap;
21  import net.sf.snmpadaptor4j.object.SnmpTrapData;
22  import net.sf.snmpadaptor4j.object.GenericSnmpTrap;
23  import net.sf.snmpadaptor4j.object.SpecificSnmpTrap;
24  import net.sf.snmpadaptor4j.object.GenericSnmpTrapType;
25  
26  /**
27   * SNMP trap sender implementation for <b>joesnmp</b> API.
28   * @author <a href="http://fr.linkedin.com/in/jpminetti/">Jean-Philippe MINETTI</a>
29   */
30  public final class OpennmsSnmpTrapSender
31  		extends OpennmsSupport
32  		implements SnmpTrapSender {
33  
34  	/**
35  	 * OID CONSTANT: Time stamp.
36  	 */
37  	private static final SnmpObjectId TIME_STAMP_OID = new SnmpObjectId("1.3.6.1.2.1.1.3.0");
38  
39  	/**
40  	 * OID CONSTANT: Type.
41  	 */
42  	private static final SnmpObjectId TYPE_OID = new SnmpObjectId("1.3.6.1.6.3.1.1.4.1.0");
43  
44  	/**
45  	 * OID CONSTANT: Agent address.
46  	 */
47  	private static final SnmpObjectId AGENT_ADDRESS_OID = new SnmpObjectId("1.3.6.1.6.3.18.1.3.0");
48  
49  	/**
50  	 * OID CONSTANT: Community name.
51  	 */
52  	private static final SnmpObjectId COMMUNITY_OID = new SnmpObjectId("1.3.6.1.6.3.18.1.4.0");
53  
54  	/**
55  	 * OID CONSTANT: Enterprise.
56  	 */
57  	private static final SnmpObjectId ENTERPRISE_OID = new SnmpObjectId("1.3.6.1.6.3.1.1.4.3.0");
58  
59  	/**
60  	 * TYPE VALUE CONSTANT: coldStart.
61  	 */
62  	private static final SnmpOid GENERIC_COLD_START_TYPE_VALUE = SnmpOid.newInstance("1.3.6.1.6.3.1.1.5.1");
63  
64  	/**
65  	 * TYPE VALUE CONSTANT: warmStart.
66  	 */
67  	private static final SnmpOid GENERIC_WARM_START_TYPE_VALUE = SnmpOid.newInstance("1.3.6.1.6.3.1.1.5.2");
68  
69  	/**
70  	 * TYPE VALUE CONSTANT: linkDown.
71  	 */
72  	private static final SnmpOid GENERIC_LINK_DOWN_TYPE_VALUE = SnmpOid.newInstance("1.3.6.1.6.3.1.1.5.3");
73  
74  	/**
75  	 * TYPE VALUE CONSTANT: linkUp.
76  	 */
77  	private static final SnmpOid GENERIC_LINK_UP_TYPE_VALUE = SnmpOid.newInstance("1.3.6.1.6.3.1.1.5.4");
78  
79  	/**
80  	 * TYPE VALUE CONSTANT: authenticationFailure.
81  	 */
82  	private static final SnmpOid GENERIC_AUTHENTICATION_FAILURE_TYPE_VALUE = SnmpOid.newInstance("1.3.6.1.6.3.1.1.5.5");
83  
84  	/**
85  	 * TYPE VALUE CONSTANT: egpNeighborLoss.
86  	 */
87  	private static final SnmpOid GENERIC_EGP_NEIGHBOR_LOSS_TYPE_VALUE = SnmpOid.newInstance("1.3.6.1.6.3.1.1.5.6");
88  
89  	/**
90  	 * Null SNMP handler.
91  	 */
92  	protected final class NullHandler
93  			implements SnmpHandler {
94  
95  		/*
96  		 * {@inheritDoc}
97  		 * @see org.opennms.protocols.snmp.SnmpHandler#snmpReceivedPdu(org.opennms.protocols.snmp.SnmpSession, int, org.opennms.protocols.snmp.SnmpPduPacket)
98  		 */
99  		public void snmpReceivedPdu (final SnmpSession session, final int command, final SnmpPduPacket pdu) {
100 			// NOP
101 		}
102 
103 		/*
104 		 * {@inheritDoc}
105 		 * @see org.opennms.protocols.snmp.SnmpHandler#snmpInternalError(org.opennms.protocols.snmp.SnmpSession, int, org.opennms.protocols.snmp.SnmpSyntax)
106 		 */
107 		public void snmpInternalError (final SnmpSession session, final int err, final SnmpSyntax pdu) {
108 			// NOP
109 		}
110 
111 		/*
112 		 * {@inheritDoc}
113 		 * @see org.opennms.protocols.snmp.SnmpHandler#snmpTimeoutError(org.opennms.protocols.snmp.SnmpSession, org.opennms.protocols.snmp.SnmpSyntax)
114 		 */
115 		public void snmpTimeoutError (final SnmpSession session, final SnmpSyntax pdu) {
116 			// NOP
117 		}
118 
119 	}
120 
121 	/**
122 	 * IP address of SNMP agent.
123 	 */
124 	private final SnmpIPAddress agentAddress;
125 
126 	/**
127 	 * IP address of SNMP manager responsible of traps handling.
128 	 */
129 	private final String managerAddress;
130 
131 	/**
132 	 * UDP port of SNMP manager responsible of traps handling.
133 	 */
134 	private final int managerPort;
135 
136 	/**
137 	 * Protocol version of SNMP manager.
138 	 */
139 	private final int managerVersion;
140 
141 	/**
142 	 * Community of SNMP manager.
143 	 */
144 	private final String managerCommunity;
145 
146 	/**
147 	 * SNMP session.
148 	 */
149 	private SnmpSession snmpSession;
150 
151 	/**
152 	 * Hidden constructor.
153 	 * @param agentAddress IP address of SNMP agent (must be a local address of the host).
154 	 * @param managerAddress IP address of SNMP manager responsible of traps handling.
155 	 * @param managerPort UDP port of SNMP manager responsible of traps handling.
156 	 * @param managerVersion Protocol version of SNMP manager.
157 	 * @param managerCommunity Community of SNMP manager.
158 	 * @see OpennmsSnmpApiFactory#newSnmpTrapSender(InetAddress, String, int, int, String)
159 	 */
160 	OpennmsSnmpTrapSender (final InetAddress agentAddress, final String managerAddress, final int managerPort, final int managerVersion,
161 			final String managerCommunity) {
162 		super();
163 		this.agentAddress = new SnmpIPAddress(agentAddress);
164 		this.managerAddress = managerAddress;
165 		this.managerPort = managerPort;
166 		this.managerVersion = managerVersion;
167 		this.managerCommunity = managerCommunity;
168 	}
169 
170 	/*
171 	 * {@inheritDoc}
172 	 * @see net.sf.snmpadaptor4j.api.SnmpTrapSender#getName()
173 	 */
174 	public String getName () {
175 		return this.managerAddress + ":" + this.managerPort + "/" + this.managerCommunity;
176 	}
177 
178 	/*
179 	 * {@inheritDoc}
180 	 * @see net.sf.snmpadaptor4j.api.SnmpTrapSender#open()
181 	 */
182 	public void open () throws Exception {
183 		synchronized (this) {
184 			if (this.snmpSession == null) {
185 				if (this.logger.isTraceEnabled()) {
186 					this.logger.trace("Connecting to " + this.managerAddress + ":" + this.managerPort + "...");
187 				}
188 				final SnmpPeer peer = new SnmpPeer(InetAddress.getByName(this.managerAddress));
189 				peer.setPort(this.managerPort);
190 				final SnmpParameters params = peer.getParameters();
191 				params.setReadCommunity(this.managerCommunity);
192 				switch (this.managerVersion) {
193 					case 1:
194 						params.setVersion(SnmpSMI.SNMPV1);
195 						break;
196 					default:
197 						params.setVersion(SnmpSMI.SNMPV2);
198 						break;
199 				}
200 				this.snmpSession = new SnmpSession(peer);
201 				this.snmpSession.setDefaultHandler(new NullHandler());
202 				Thread.sleep(100);
203 				this.logger.trace("Connected");
204 			}
205 			else if (this.logger.isTraceEnabled()) {
206 				this.logger.trace(this.managerAddress + ":" + this.managerPort + " already connected");
207 			}
208 		}
209 	}
210 
211 	/*
212 	 * {@inheritDoc}
213 	 * @see net.sf.snmpadaptor4j.api.SnmpTrapSender#close()
214 	 */
215 	public void close () {
216 		synchronized (this) {
217 			if (this.snmpSession != null) {
218 				if (this.logger.isTraceEnabled()) {
219 					this.logger.trace("Disconnecting from " + this.managerAddress + ":" + this.managerPort + "...");
220 				}
221 				this.snmpSession.close();
222 				this.snmpSession = null;
223 				this.logger.trace("Disconnected");
224 			}
225 			else if (this.logger.isTraceEnabled()) {
226 				this.logger.trace(this.managerAddress + ":" + this.managerPort + " already disconnected");
227 			}
228 		}
229 	}
230 
231 	/*
232 	 * {@inheritDoc}
233 	 * @see net.sf.snmpadaptor4j.api.SnmpTrapSender#isConnected()
234 	 */
235 	public boolean isConnected () {
236 		return (this.snmpSession != null);
237 	}
238 
239 	/*
240 	 * {@inheritDoc}
241 	 * @see net.sf.snmpadaptor4j.api.SnmpTrapSender#send(net.sf.snmpadaptor4j.object.SnmpTrap)
242 	 */
243 	public void send (final SnmpTrap trap) throws Exception {
244 		switch (this.managerVersion) {
245 			case 1:
246 				sendV1(trap);
247 				break;
248 			default:
249 				sendV2(trap);
250 				break;
251 		}
252 	}
253 
254 	/**
255 	 * Sends a SNMP trap V1 to the manager.
256 	 * @param trap Object representing a specific or generic SNMP trap.
257 	 * @throws Exception Exception if an error has occurred.
258 	 */
259 	private void sendV1 (final SnmpTrap trap) throws Exception {
260 
261 		// Packet building
262 		final SnmpPduTrap trapPdu = new SnmpPduTrap();
263 		trapPdu.setTimeStamp(trap.getTimeStamp());
264 		if (trap.getSource() == null) {
265 			throw new Exception("The source of trap is missing");
266 		}
267 		trapPdu.setEnterprise(new SnmpObjectId(trap.getSource().getOid()));
268 		trapPdu.setAgentAddress(this.agentAddress);
269 		if (trap instanceof SpecificSnmpTrap) {
270 			trapPdu.setGeneric(SnmpPduTrap.GenericEnterpriseSpecific);
271 			trapPdu.setSpecific(((SpecificSnmpTrap) trap).getType());
272 		}
273 		else if (trap instanceof GenericSnmpTrap) {
274 			final GenericSnmpTrap genericTrap = (GenericSnmpTrap) trap;
275 			if (genericTrap.getType() == GenericSnmpTrapType.coldStart) {
276 				trapPdu.setGeneric(SnmpPduTrap.GenericColdStart);
277 			}
278 			else if (genericTrap.getType() == GenericSnmpTrapType.warmStart) {
279 				trapPdu.setGeneric(SnmpPduTrap.GenericWarmStart);
280 			}
281 			else if (genericTrap.getType() == GenericSnmpTrapType.linkDown) {
282 				trapPdu.setGeneric(SnmpPduTrap.GenericLinkDown);
283 			}
284 			else if (genericTrap.getType() == GenericSnmpTrapType.linkUp) {
285 				trapPdu.setGeneric(SnmpPduTrap.GenericLinkUp);
286 			}
287 			else if (genericTrap.getType() == GenericSnmpTrapType.authenticationFailure) {
288 				trapPdu.setGeneric(SnmpPduTrap.GenericAuthenticationFailure);
289 			}
290 			else if (genericTrap.getType() == GenericSnmpTrapType.egpNeighborLoss) {
291 				trapPdu.setGeneric(SnmpPduTrap.GenericEgpNeighborLoss);
292 			}
293 			else {
294 				throw new Exception("Generic trap type unknown");
295 			}
296 			trapPdu.setSpecific(0);
297 		}
298 		else {
299 			throw new Exception("Trap type unknown");
300 		}
301 		for (Entry<SnmpOid, SnmpTrapData> entry : trap.getDataMap().entrySet()) {
302 			trapPdu.addVarBind(new SnmpVarBind(new SnmpObjectId(entry.getKey().getOid()), newSnmpValue(entry.getValue().getType(), entry.getValue().getValue())));
303 		}
304 
305 		// Sending
306 		synchronized (this) {
307 			if (this.logger.isTraceEnabled()) {
308 				this.logger.trace(trap + " sending to " + this.managerAddress + ":" + this.managerPort + "...");
309 			}
310 			if (this.snmpSession == null) {
311 				throw new Exception("The connection to the SNMP manager is closed");
312 			}
313 			this.snmpSession.send(trapPdu);
314 			if (this.logger.isTraceEnabled()) {
315 				this.logger.trace(trap + " sent");
316 			}
317 		}
318 
319 	}
320 
321 	/**
322 	 * Sends a SNMP trap V2 to the manager.
323 	 * @param trap Object representing a SNMP trap V2.
324 	 * @throws Exception Exception if an error has occurred.
325 	 */
326 	private void sendV2 (final SnmpTrap trap) throws Exception {
327 
328 		// Packet building
329 		final SnmpPduRequest trapPdu = new SnmpPduRequest(SnmpPduPacket.V2TRAP);
330 		trapPdu.addVarBind(new SnmpVarBind(OpennmsSnmpTrapSender.TIME_STAMP_OID, newSnmpValue(SnmpDataType.timeTicks, new Long(trap.getTimeStamp()))));
331 		if (trap.getSource() == null) {
332 			throw new Exception("The source of trap is missing");
333 		}
334 		SnmpOid typeValue;
335 		if (trap instanceof SpecificSnmpTrap) {
336 			typeValue = SnmpOid.newInstance(trap.getSource(), 0, ((SpecificSnmpTrap) trap).getType() + 1);
337 		}
338 		else if (trap instanceof GenericSnmpTrap) {
339 			final GenericSnmpTrap genericTrap = (GenericSnmpTrap) trap;
340 			if (genericTrap.getType() == GenericSnmpTrapType.coldStart) {
341 				typeValue = OpennmsSnmpTrapSender.GENERIC_COLD_START_TYPE_VALUE;
342 			}
343 			else if (genericTrap.getType() == GenericSnmpTrapType.warmStart) {
344 				typeValue = OpennmsSnmpTrapSender.GENERIC_WARM_START_TYPE_VALUE;
345 			}
346 			else if (genericTrap.getType() == GenericSnmpTrapType.linkDown) {
347 				typeValue = OpennmsSnmpTrapSender.GENERIC_LINK_DOWN_TYPE_VALUE;
348 			}
349 			else if (genericTrap.getType() == GenericSnmpTrapType.linkUp) {
350 				typeValue = OpennmsSnmpTrapSender.GENERIC_LINK_UP_TYPE_VALUE;
351 			}
352 			else if (genericTrap.getType() == GenericSnmpTrapType.authenticationFailure) {
353 				typeValue = OpennmsSnmpTrapSender.GENERIC_AUTHENTICATION_FAILURE_TYPE_VALUE;
354 			}
355 			else if (genericTrap.getType() == GenericSnmpTrapType.egpNeighborLoss) {
356 				typeValue = OpennmsSnmpTrapSender.GENERIC_EGP_NEIGHBOR_LOSS_TYPE_VALUE;
357 			}
358 			else {
359 				throw new Exception("Generic trap type unknown");
360 			}
361 		}
362 		else {
363 			throw new Exception("Trap type unknown");
364 		}
365 		trapPdu.addVarBind(new SnmpVarBind(OpennmsSnmpTrapSender.TYPE_OID, newSnmpValue(SnmpDataType.objectIdentifier, typeValue)));
366 		trapPdu.addVarBind(new SnmpVarBind(OpennmsSnmpTrapSender.AGENT_ADDRESS_OID, newSnmpValue(SnmpDataType.ipAddress, this.agentAddress.convertToIpAddress())));
367 		trapPdu.addVarBind(new SnmpVarBind(OpennmsSnmpTrapSender.COMMUNITY_OID, newSnmpValue(SnmpDataType.octetString, this.managerCommunity)));
368 		trapPdu.addVarBind(new SnmpVarBind(OpennmsSnmpTrapSender.ENTERPRISE_OID, newSnmpValue(SnmpDataType.objectIdentifier, trap.getSource())));
369 		for (Entry<SnmpOid, SnmpTrapData> entry : trap.getDataMap().entrySet()) {
370 			trapPdu.addVarBind(new SnmpVarBind(new SnmpObjectId(entry.getKey().getOid()), newSnmpValue(entry.getValue().getType(), entry.getValue().getValue())));
371 		}
372 
373 		// Sending
374 		synchronized (this) {
375 			if (this.logger.isTraceEnabled()) {
376 				this.logger.trace(trap + " sending to " + this.managerAddress + ":" + this.managerPort + "...");
377 			}
378 			if (this.snmpSession == null) {
379 				throw new Exception("The connection to the SNMP manager is closed");
380 			}
381 			this.snmpSession.send(trapPdu);
382 			if (this.logger.isTraceEnabled()) {
383 				this.logger.trace(trap + " sent");
384 			}
385 		}
386 
387 	}
388 
389 	/*
390 	 * {@inheritDoc}
391 	 * @see java.lang.Object#toString()
392 	 */
393 	@Override
394 	public String toString () {
395 		return "SnmpTrapSender:opennms[" + getName() + "]";
396 	}
397 
398 }