1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.waarp.snmp;
21
22 import org.snmp4j.TransportMapping;
23 import org.snmp4j.agent.BaseAgent;
24 import org.snmp4j.agent.CommandProcessor;
25 import org.snmp4j.agent.DuplicateRegistrationException;
26 import org.snmp4j.agent.MOGroup;
27 import org.snmp4j.agent.mo.snmp.RowStatus;
28 import org.snmp4j.agent.mo.snmp.SNMPv2MIB;
29 import org.snmp4j.agent.mo.snmp.SnmpCommunityMIB;
30 import org.snmp4j.agent.mo.snmp.SnmpCommunityMIB.SnmpCommunityEntryRow;
31 import org.snmp4j.agent.mo.snmp.SnmpNotificationMIB;
32 import org.snmp4j.agent.mo.snmp.SnmpTargetMIB;
33 import org.snmp4j.agent.mo.snmp.StorageType;
34 import org.snmp4j.agent.mo.snmp.VacmMIB;
35 import org.snmp4j.agent.security.MutableVACM;
36 import org.snmp4j.mp.MPv3;
37 import org.snmp4j.mp.MessageProcessingModel;
38 import org.snmp4j.mp.SnmpConstants;
39 import org.snmp4j.security.SecurityLevel;
40 import org.snmp4j.security.SecurityModel;
41 import org.snmp4j.security.USM;
42 import org.snmp4j.security.UsmUser;
43 import org.snmp4j.smi.Address;
44 import org.snmp4j.smi.GenericAddress;
45 import org.snmp4j.smi.Integer32;
46 import org.snmp4j.smi.OID;
47 import org.snmp4j.smi.OctetString;
48 import org.snmp4j.smi.Variable;
49 import org.snmp4j.smi.VariableBinding;
50 import org.snmp4j.transport.TransportMappings;
51 import org.snmp4j.util.ThreadPool;
52 import org.snmp4j.util.WorkerPool;
53 import org.waarp.common.logging.SysErrLogger;
54 import org.waarp.common.logging.WaarpLogger;
55 import org.waarp.common.logging.WaarpLoggerFactory;
56 import org.waarp.snmp.SnmpConfiguration.TargetElement;
57 import org.waarp.snmp.interf.WaarpInterfaceMib;
58 import org.waarp.snmp.interf.WaarpInterfaceMib.TrapLevel;
59 import org.waarp.snmp.interf.WaarpInterfaceMonitor;
60
61 import java.io.File;
62 import java.io.IOException;
63 import java.util.List;
64
65
66
67
68
69 public class WaarpSnmpAgent extends BaseAgent {
70
71
72
73 private static final WaarpLogger logger =
74 WaarpLoggerFactory.getLogger(WaarpSnmpAgent.class);
75
76 private String[] address = { SnmpConfiguration.DEFAULTADDRESS };
77
78 private final boolean isFilterAccessEnabled;
79
80 private boolean useTrap = true;
81
82 private int trapLevel;
83
84 private final List<UsmUser> listUsmUser;
85
86 private final List<TargetElement> listTargetElements;
87
88 private final boolean hasV2;
89
90 private final boolean hasV3;
91
92 private final long systemTimeStart = System.currentTimeMillis();
93
94 private final WorkerPool workerPool;
95
96
97
98 private WaarpInterfaceMonitor monitor;
99
100
101
102 private WaarpInterfaceMib mib;
103
104
105
106
107
108
109
110
111 public WaarpSnmpAgent(final File configurationFile,
112 final WaarpInterfaceMonitor monitor,
113 final WaarpInterfaceMib mib)
114 throws IllegalArgumentException {
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130 super(new File(configurationFile.getParentFile(), "dummyConf.agent"),
131 new File(configurationFile.getParentFile(), "dummyBootCounter.agent"),
132 new CommandProcessor(new OctetString(MPv3.createLocalEngineID())));
133 if (!SnmpConfiguration.setConfigurationFromXml(configurationFile)) {
134 throw new IllegalArgumentException("Cannot load configuration");
135 }
136 address = SnmpConfiguration.address;
137 final int nbThread = SnmpConfiguration.nbThread;
138 isFilterAccessEnabled = SnmpConfiguration.isFilterAccessEnabled;
139 useTrap = SnmpConfiguration.isUsingTrap;
140 setTrapLevel(SnmpConfiguration.trapLevel);
141 listUsmUser = SnmpConfiguration.listUsmUser;
142 listTargetElements = SnmpConfiguration.listTargetElements;
143 hasV2 = SnmpConfiguration.hasV2;
144 hasV3 = SnmpConfiguration.hasV3;
145
146 logger.debug("SNMP Configuration loaded: {}:{}", address[0], nbThread);
147 workerPool = ThreadPool.create("SnmpRequestPool", nbThread);
148 agent.setWorkerPool(workerPool);
149 setMonitor(monitor);
150 getMonitor().setAgent(this);
151 setMib(mib);
152 getMib().setAgent(this);
153 }
154
155
156
157
158 public final WaarpInterfaceMonitor getMonitor() {
159 return monitor;
160 }
161
162
163
164
165 public final WaarpInterfaceMib getMib() {
166 return mib;
167 }
168
169
170
171
172 public final long getUptime() {
173 return getSnmpv2MIB().getUpTime().toMilliseconds();
174 }
175
176
177
178
179 public final long getUptimeSystemTime() {
180 return systemTimeStart;
181 }
182
183
184
185
186 @Override
187 protected final void registerManagedObjects() {
188 logger.debug("Registers");
189 try {
190 getMib().registerMOs(server, null);
191 } catch (final DuplicateRegistrationException e) {
192 logger.error("Cannot register Mib", e);
193 }
194 }
195
196
197
198
199 @Override
200 protected final void unregisterManagedObjects() {
201 logger.debug("Unregisters");
202 getMib().unregisterMOs(server, null);
203 }
204
205
206
207
208 public final void unregisterManagedObject(final MOGroup moGroup) {
209 logger.debug("Unregister {}", moGroup);
210 moGroup.unregisterMOs(server, getContext(moGroup));
211 }
212
213
214
215
216
217 @Override
218 protected final void addUsmUser(final USM usm) {
219 for (final UsmUser userlist : listUsmUser) {
220 logger.debug("User: {}", userlist);
221 usm.addUser(userlist.getSecurityName(), usm.getLocalEngineID(), userlist);
222 }
223 final UsmUser usernotify =
224 new UsmUser(new OctetString(SnmpConfiguration.V3NOTIFY), null, null,
225 null, null);
226 usm.addUser(usernotify.getSecurityName(), null, usernotify);
227 }
228
229
230
231
232 @Override
233 protected final void addNotificationTargets(final SnmpTargetMIB targetMIB,
234 final SnmpNotificationMIB notificationMIB) {
235 targetMIB.addDefaultTDomains();
236
237 for (final TargetElement element : listTargetElements) {
238 logger.debug("AddTarget: {}", element);
239 targetMIB.addTargetAddress(element.name, element.transportDomain,
240 element.address, element.timeout,
241 element.retries, element.tagList,
242 element.params, element.storageType);
243 }
244
245
246
247
248
249
250
251
252
253 logger.debug("HasV2: {} HasV3: {}", hasV2, hasV3);
254 if (hasV2) {
255 targetMIB.addTargetParams(new OctetString(SnmpConfiguration.V2C),
256 MessageProcessingModel.MPv2c,
257 SecurityModel.SECURITY_MODEL_SNMPv2c,
258 new OctetString("cpublic"),
259 SecurityLevel.AUTH_PRIV, StorageType.permanent);
260 }
261 if (hasV3) {
262 targetMIB.addTargetParams(new OctetString(SnmpConfiguration.V3NOTIFY),
263 MessageProcessingModel.MPv3,
264 SecurityModel.SECURITY_MODEL_USM,
265 new OctetString("v3notify"),
266 SecurityLevel.NOAUTH_NOPRIV,
267 StorageType.permanent);
268 }
269 int trapOrInform = SnmpNotificationMIB.SnmpNotifyTypeEnum.inform;
270 if (useTrap) {
271 trapOrInform = SnmpNotificationMIB.SnmpNotifyTypeEnum.trap;
272 }
273 notificationMIB.addNotifyEntry(new OctetString("default"),
274 new OctetString(SnmpConfiguration.NOTIFY),
275 trapOrInform, StorageType.permanent);
276 }
277
278
279
280
281
282
283 @Override
284 protected final void addViews(final VacmMIB vacm) {
285 vacm.addGroup(SecurityModel.SECURITY_MODEL_SNMPv1,
286 new OctetString("cpublic"), new OctetString("v1v2group"),
287 StorageType.nonVolatile);
288 vacm.addGroup(SecurityModel.SECURITY_MODEL_SNMPv2c,
289 new OctetString("cpublic"), new OctetString("v1v2group"),
290 StorageType.nonVolatile);
291 vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, new OctetString("v3notify"),
292 new OctetString("v3group"), StorageType.nonVolatile);
293
294 for (final UsmUser user : listUsmUser) {
295 logger.debug("Groups: {} Restricted? {}", user.getSecurityName(),
296 user.getPrivacyProtocol() == null);
297 if (user.getPrivacyProtocol() == null) {
298 vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
299 new OctetString(user.getSecurityName()),
300 new OctetString("v3restricted"), StorageType.nonVolatile);
301 } else {
302 vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
303 new OctetString(user.getSecurityName()),
304 new OctetString("v3group"), StorageType.nonVolatile);
305 }
306 }
307
308 vacm.addAccess(new OctetString("v1v2group"), new OctetString("public"),
309 SecurityModel.SECURITY_MODEL_ANY,
310 SecurityLevel.NOAUTH_NOPRIV, MutableVACM.VACM_MATCH_EXACT,
311 new OctetString("fullReadView"),
312 new OctetString("fullWriteView"),
313 new OctetString("fullNotifyView"), StorageType.nonVolatile);
314 vacm.addAccess(new OctetString("v3group"), new OctetString(),
315 SecurityModel.SECURITY_MODEL_USM, SecurityLevel.AUTH_PRIV,
316 MutableVACM.VACM_MATCH_EXACT,
317 new OctetString("fullReadView"),
318 new OctetString("fullWriteView"),
319 new OctetString("fullNotifyView"), StorageType.nonVolatile);
320 vacm.addAccess(new OctetString("v3restricted"), new OctetString(),
321 SecurityModel.SECURITY_MODEL_USM,
322 SecurityLevel.NOAUTH_NOPRIV, MutableVACM.VACM_MATCH_EXACT,
323 new OctetString("restrictedReadView"),
324 new OctetString("restrictedWriteView"),
325 new OctetString("restrictedNotifyView"),
326 StorageType.nonVolatile);
327
328 vacm.addViewTreeFamily(new OctetString("fullReadView"), new OID("1.3"),
329 new OctetString(), VacmMIB.vacmViewIncluded,
330 StorageType.nonVolatile);
331 vacm.addViewTreeFamily(new OctetString("fullWriteView"), new OID("1.3"),
332 new OctetString(), VacmMIB.vacmViewIncluded,
333 StorageType.nonVolatile);
334 vacm.addViewTreeFamily(new OctetString("fullNotifyView"), new OID("1.3"),
335 new OctetString(), VacmMIB.vacmViewIncluded,
336 StorageType.nonVolatile);
337
338 vacm.addViewTreeFamily(new OctetString("restrictedReadView"),
339 new OID("1.3.6.1.2"), new OctetString(),
340 VacmMIB.vacmViewIncluded, StorageType.nonVolatile);
341 vacm.addViewTreeFamily(new OctetString("restrictedWriteView"),
342 new OID("1.3.6.1.2.1"), new OctetString(),
343 VacmMIB.vacmViewIncluded, StorageType.nonVolatile);
344 vacm.addViewTreeFamily(new OctetString("restrictedNotifyView"),
345 new OID("1.3.6.1.2"), new OctetString(),
346 VacmMIB.vacmViewIncluded, StorageType.nonVolatile);
347 vacm.addViewTreeFamily(new OctetString("restrictedNotifyView"),
348 new OID("1.3.6.1.6.3.1"), new OctetString(),
349 VacmMIB.vacmViewIncluded, StorageType.nonVolatile);
350 }
351
352
353
354
355
356
357
358 @Override
359 protected final void addCommunities(final SnmpCommunityMIB communityMIB) {
360 final Variable[] com2sec = {
361 new OctetString("public"),
362 new OctetString("cpublic"),
363 getAgent().getContextEngineID(),
364 new OctetString("public"),
365 new OctetString(),
366 new Integer32(StorageType.nonVolatile),
367 new Integer32(RowStatus.active)
368 };
369 final SnmpCommunityEntryRow row = communityMIB.getSnmpCommunityEntry()
370 .createRow(new OctetString(
371 "public2public").toSubIndex(
372 true), com2sec);
373 communityMIB.getSnmpCommunityEntry().addRow(row);
374 if (isFilterAccessEnabled) {
375 snmpCommunityMIB.setSourceAddressFiltering(true);
376 }
377 }
378
379 @Override
380 protected final void initTransportMappings() throws IOException {
381 final TransportMapping<?>[] testMappings =
382 new TransportMapping[address.length];
383 int nb = 0;
384 for (final String addres : address) {
385 final Address addr = GenericAddress.parse(addres);
386 if (addr != null) {
387 logger.info("SNMP Agent InitTransport: {} {}",
388 addr.getClass().getSimpleName(), addr);
389 final TransportMapping<?> tm;
390 try {
391 tm = TransportMappings.getInstance().createTransportMapping(addr);
392 } catch (final RuntimeException e) {
393 continue;
394 }
395 if (tm != null) {
396 testMappings[nb] = tm;
397 nb++;
398 }
399 }
400 }
401 if (nb > 0) {
402 transportMappings = new TransportMapping<?>[nb];
403 System.arraycopy(testMappings, 0, transportMappings, 0, nb);
404 } else {
405 transportMappings = null;
406 throw new IOException("No address to connect");
407 }
408 }
409
410
411
412
413
414
415
416 public final void start() throws IOException {
417 logger.debug("WaarpSnmpAgent starting: {} 1 on {}", address[0],
418 address.length);
419 try {
420 init();
421 } catch (final IOException e) {
422 logger.warn("Error while SNMP starts " + " : {}", e.getMessage());
423 throw e;
424 }
425 addShutdownHook();
426 getServer().addContext(new OctetString("public"));
427 finishInit();
428 run();
429 if (TrapLevel.StartStop.isLevelValid(getTrapLevel())) {
430 sendColdStartNotification();
431 }
432 }
433
434 @Override
435 protected final void sendColdStartNotification() {
436 logger.debug("ColdStartNotification: {}",
437 getMib().getBaseOidStartOrShutdown());
438 final SNMPv2MIB snmpv2 = getMib().getSNMPv2MIB();
439 notificationOriginator.notify(new OctetString("public"),
440 SnmpConstants.coldStart,
441 new VariableBinding[] {
442 new VariableBinding(
443 getMib().getBaseOidStartOrShutdown(),
444 new OctetString("Startup Service")),
445 new VariableBinding(
446 SnmpConstants.sysDescr,
447 snmpv2.getDescr()),
448 new VariableBinding(
449 SnmpConstants.sysObjectID,
450 snmpv2.getObjectID()),
451 new VariableBinding(
452 SnmpConstants.sysContact,
453 snmpv2.getContact()),
454 new VariableBinding(SnmpConstants.sysName,
455 snmpv2.getName()),
456 new VariableBinding(
457 SnmpConstants.sysLocation,
458 snmpv2.getLocation())
459 });
460 }
461
462
463
464
465 protected final void sendShutdownNotification() {
466 if (getMib() == null || notificationOriginator == null) {
467 return;
468 }
469 final SNMPv2MIB snmpv2 = getMib().getSNMPv2MIB();
470 notificationOriginator.notify(new OctetString("public"),
471 SnmpConstants.linkDown,
472 new VariableBinding[] {
473 new VariableBinding(
474 getMib().getBaseOidStartOrShutdown(),
475 new OctetString("Shutdown Service")),
476 new VariableBinding(
477 SnmpConstants.sysDescr,
478 snmpv2.getDescr()),
479 new VariableBinding(
480 SnmpConstants.sysObjectID,
481 snmpv2.getObjectID()),
482 new VariableBinding(
483 SnmpConstants.sysContact,
484 snmpv2.getContact()),
485 new VariableBinding(SnmpConstants.sysName,
486 snmpv2.getName()),
487 new VariableBinding(
488 SnmpConstants.sysLocation,
489 snmpv2.getLocation())
490 });
491 try {
492 Thread.sleep(100);
493 } catch (final InterruptedException e) {
494 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
495 }
496 }
497
498 @Override
499 public final void stop() {
500 logger.info("Stopping SNMP support");
501 if (TrapLevel.StartStop.isLevelValid(getTrapLevel())) {
502 sendShutdownNotification();
503 }
504 if (session != null) {
505 super.stop();
506 }
507 if (getMonitor() != null) {
508 getMonitor().releaseResources();
509 try {
510 Thread.sleep(100);
511 } catch (final InterruptedException e) {
512 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
513 }
514 if (workerPool != null) {
515 workerPool.cancel();
516 }
517 }
518 }
519
520
521
522
523 public final int getTrapLevel() {
524 return trapLevel;
525 }
526
527
528
529
530 public final void setTrapLevel(final int trapLevel) {
531 this.trapLevel = trapLevel;
532 }
533
534
535
536
537 private void setMonitor(final WaarpInterfaceMonitor monitor) {
538 this.monitor = monitor;
539 }
540
541
542
543
544 private void setMib(final WaarpInterfaceMib mib) {
545 this.mib = mib;
546 }
547 }