blob: a90a3f10121bffe4b3fa2f1bd91b0314d7b729f1 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2001-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25package com.sun.jmx.snmp.internal;
26
27import java.net.InetAddress;
28import java.net.UnknownHostException;
29import java.util.Hashtable;
30import java.util.logging.Level;
31import java.io.Serializable;
32
33import com.sun.jmx.snmp.SnmpDefinitions;
34import com.sun.jmx.snmp.SnmpEngineId;
35import com.sun.jmx.snmp.SnmpEngine;
36import com.sun.jmx.snmp.SnmpUsmKeyHandler;
37import com.sun.jmx.snmp.SnmpEngineFactory;
38import com.sun.jmx.snmp.SnmpUnknownModelException;
39
40import com.sun.jmx.snmp.internal.SnmpTools;
41import com.sun.jmx.snmp.SnmpBadSecurityLevelException;
42import static com.sun.jmx.defaults.JmxProperties.SNMP_LOGGER;
43
44/**
45 * This engine is conformant with the RFC 2571. It is the main object within
46 * an SNMP entity (agent, manager...).
47 * To an engine is associated an {@link com.sun.jmx.snmp.SnmpEngineId}.
48 * The way the engineId is retrieved is linked to the way the engine is
49 * instantiated. See each <CODE>SnmpEngine</CODE> constructor for more details.
50 * An engine is composed of a set of sub systems
51 * {@link com.sun.jmx.snmp.internal.SnmpSubSystem}. An <CODE>SNMP</CODE>
52 * engine can contain a:
53 *<ul>
54 *<li> Message Processing Sub System :
55 * {@link com.sun.jmx.snmp.internal.SnmpMsgProcessingSubSystem}</li>
56 *<li> Security Sub System :
57 * {@link com.sun.jmx.snmp.internal.SnmpSecuritySubSystem} </li>
58 *<li> Access Control Sub System :
59 * {@link com.sun.jmx.snmp.internal.SnmpAccessControlSubSystem}</li>
60 *</ul>
61 *<P> Each sub system contains a set of models. A model is an implementation
62 * of a particular treatement (eg: the User based Security Model defined in
63 * RFC 2574 is a functional element dealing with authentication and privacy).
64 *</P>
65 * Engine instantiation is based on a factory. This factory, implementing
66 * mandatorily {@link com.sun.jmx.snmp.SnmpEngineFactory SnmpEngineFactory}
67 * is set in the method <CODE>setFactory</CODE>.
68 * <p><b>This API is a Sun Microsystems internal API and is subject
69 * to change without notice.</b></p>
70 * @since 1.5
71 */
72public class SnmpEngineImpl implements SnmpEngine, Serializable {
73 private static final long serialVersionUID = -2564301391365614725L;
74
75 /**
76 * Security level. No authentication, no privacy. Value is 0,
77 * as defined in RFC 2572
78 */
79 public static final int noAuthNoPriv = 0;
80 /**
81 * Security level. Authentication, no privacy. Value is 1, as
82 * defined in RFC 2572
83 */
84 public static final int authNoPriv = 1;
85 /**
86 * Security level. Authentication, privacy. Value is 3,
87 * as defined in RFC 2572
88 */
89 public static final int authPriv = 3;
90 /**
91 * Flag that indicates that a report is to be sent. Value is 4, as defined in RFC 2572
92 */
93 public static final int reportableFlag = 4;
94
95 /**
96 * Mask used to isolate authentication information within a message flag.
97 */
98 public static final int authMask = 1;
99 /**
100 * Mask used to isolate privacy information within a message flag.
101 */
102 public static final int privMask = 2;
103 /**
104 * Mask used to isolate authentication and privacy information within a message flag.
105 */
106 public static final int authPrivMask = 3;
107
108 private SnmpEngineId engineid = null;
109 private SnmpEngineFactory factory = null;
110 private long startTime = 0;
111
112 private int boot = 0;
113 private boolean checkOid = false;
114
115 transient private SnmpUsmKeyHandler usmKeyHandler = null;
116 transient private SnmpLcd lcd = null;
117
118 transient private SnmpSecuritySubSystem securitySub = null;
119
120 transient private SnmpMsgProcessingSubSystem messageSub = null;
121
122 transient private SnmpAccessControlSubSystem accessSub = null;
123
124 /**
125 * Gets the engine time in seconds. This is the time from the last reboot.
126 * @return The time from the last reboot.
127 */
128 public synchronized int getEngineTime() {
129 //We do the counter wrap in a lazt way. Each time Engine is asked for his time it checks. So if nobody use the Engine, the time can wrap and wrap again without incrementing nb boot. We can imagine that it is irrelevant due to the amount of time needed to wrap.
130 long delta = (System.currentTimeMillis() / 1000) - startTime;
131 if(delta > 0x7FFFFFFF) {
132 //67 years of running. That is a great thing!
133 //Reinitialize startTime.
134 startTime = System.currentTimeMillis() / 1000;
135
136 //Can't do anything with this counter.
137 if(boot != 0x7FFFFFFF)
138 boot += 1;
139 //Store for future use.
140 storeNBBoots(boot);
141 }
142
143 return (int) ((System.currentTimeMillis() / 1000) - startTime);
144 }
145
146 /**
147 * Gets the engine Id. This is unique for each engine.
148 * @return The engine Id object.
149 */
150 public SnmpEngineId getEngineId() {
151 return engineid;
152 }
153
154 /**
155 * Gets the Usm key handler.
156 * @return The key handler.
157 */
158 public SnmpUsmKeyHandler getUsmKeyHandler() {
159 return usmKeyHandler;
160 }
161
162 /**
163 * Gets the engine Lcd.
164 * @return The engine Lcd.
165 */
166 public SnmpLcd getLcd() {
167 return lcd;
168 }
169 /**
170 * Gets the engine boot number. This is the number of time this engine has rebooted. Each time an <CODE>SnmpEngine</CODE> is instantiated, it will read this value in its Lcd, and store back the value incremented by one.
171 * @return The engine's number of reboot.
172 */
173 public int getEngineBoots() {
174 return boot;
175 }
176
177 /**
178 * Constructor. A Local Configuration Datastore is passed to the engine. It will be used to store and retrieve data (engine Id, engine boots).
179 * <P> WARNING : The SnmpEngineId is computed as follow:
180 * <ul>
181 * <li> If an lcd file is provided containing the property "localEngineID", this property value is used.</li>.
182 * <li> If not, if the passed engineID is not null, this engine ID is used.</li>
183 * <li> If not, a time based engineID is computed.</li>
184 * </ul>
185 * This constructor should be called by an <CODE>SnmpEngineFactory</CODE>. Don't call it directly.
186 * @param fact The factory used to instantiate this engine.
187 * @param lcd The local configuration datastore.
188 * @param engineid The engine ID to use. If null is provided, an SnmpEngineId is computed using the current time.
189 * @throws UnknownHostException Exception thrown, if the host name located in the property "localEngineID" is invalid.
190 */
191 public SnmpEngineImpl(SnmpEngineFactory fact,
192 SnmpLcd lcd,
193 SnmpEngineId engineid) throws UnknownHostException {
194
195 init(lcd, fact);
196 initEngineID();
197 if(this.engineid == null) {
198 if(engineid != null)
199 this.engineid = engineid;
200 else
201 this.engineid = SnmpEngineId.createEngineId();
202 }
203 lcd.storeEngineId(this.engineid);
204 if (SNMP_LOGGER.isLoggable(Level.FINER)) {
205 SNMP_LOGGER.logp(Level.FINER, SnmpEngineImpl.class.getName(),
206 "SnmpEngineImpl(SnmpEngineFactory,SnmpLcd,SnmpEngineId)",
207 "LOCAL ENGINE ID: " + this.engineid);
208 }
209 }
210 /**
211 * Constructor. A Local Configuration Datastore is passed to the engine. It will be used to store and retrieve data (engine ID, engine boots).
212 * <P> WARNING : The SnmpEngineId is computed as follow:
213 * <ul>
214 * <li> If an lcd file is provided containing the property "localEngineID", this property value is used.</li>.
215 * <li> If not, the passed address and port are used to compute one.</li>
216 * </ul>
217 * This constructor should be called by an <CODE>SnmpEngineFactory</CODE>. Don't call it directly.
218 * @param fact The factory used to instantiate this engine.
219 * @param lcd The local configuration datastore.
220 * @param port UDP port to use in order to calculate the engine ID.
221 * @param address An IP address used to calculate the engine ID.
222 * @throws UnknownHostException Exception thrown, if the host name located in the property "localEngineID" is invalid.
223 */
224 public SnmpEngineImpl(SnmpEngineFactory fact,
225 SnmpLcd lcd,
226 InetAddress address,
227 int port) throws UnknownHostException {
228 init(lcd, fact);
229 initEngineID();
230 if(engineid == null)
231 engineid = SnmpEngineId.createEngineId(address, port);
232
233 lcd.storeEngineId(engineid);
234
235 if (SNMP_LOGGER.isLoggable(Level.FINER)) {
236 SNMP_LOGGER.logp(Level.FINER, SnmpEngineImpl.class.getName(),
237 "SnmpEngineImpl(SnmpEngineFactory,SnmpLcd,InetAddress,int)",
238 "LOCAL ENGINE ID: " + engineid + " / " +
239 "LOCAL ENGINE NB BOOTS: " + boot + " / " +
240 "LOCAL ENGINE START TIME: " + getEngineTime());
241 }
242 }
243
244 /**
245 * Constructor. A Local Configuration Datastore is passed to the engine. It will be used to store and retrieve data (engine ID, engine boots).
246 * <P> WARNING : The SnmpEngineId is computed as follow:
247 * <ul>
248 * <li> If an lcd file is provided containing the property "localEngineID", this property value is used.</li>.
249 * <li> If not, The passed port is used to compute one.</li>
250 * </ul>
251 * This constructor should be called by an <CODE>SnmpEngineFactory</CODE>. Don't call it directly.
252 * @param fact The factory used to instantiate this engine.
253 * @param lcd The local configuration datastore
254 * @param port UDP port to use in order to calculate the engine ID.
255 * @throws UnknownHostException Exception thrown, if the host name located in the property "localEngineID" is invalid.
256 */
257 public SnmpEngineImpl(SnmpEngineFactory fact,
258 SnmpLcd lcd,
259 int port) throws UnknownHostException {
260 init(lcd, fact);
261 initEngineID();
262 if(engineid == null)
263 engineid = SnmpEngineId.createEngineId(port);
264
265 lcd.storeEngineId(engineid);
266
267 if (SNMP_LOGGER.isLoggable(Level.FINER)) {
268 SNMP_LOGGER.logp(Level.FINER, SnmpEngineImpl.class.getName(),
269 "SnmpEngineImpl(SnmpEngineFactory,SnmpLcd,int)",
270 "LOCAL ENGINE ID: " + engineid + " / " +
271 "LOCAL ENGINE NB BOOTS: " + boot + " / " +
272 "LOCAL ENGINE START TIME: " + getEngineTime());
273 }
274 }
275
276 /**
277 * Constructor. A Local Configuration Datastore is passed to the engine. It will be used to store and retrieve data (engine ID, engine boots).
278 * <P> WARNING : The SnmpEngineId is computed as follow:
279 * <ul>
280 * <li> If an lcd file is provided containing the property "localEngineID", this property value is used.</li>.
281 * <li> If not, a time based engineID is computed.</li>
282 * </ul>
283 * When no configuration nor java property is set for the engine ID value, a unique time based engine ID will be generated.
284 * This constructor should be called by an <CODE>SnmpEngineFactory</CODE>. Don't call it directly.
285 * @param fact The factory used to instantiate this engine.
286 * @param lcd The local configuration datastore.
287 */
288 public SnmpEngineImpl(SnmpEngineFactory fact,
289 SnmpLcd lcd) throws UnknownHostException {
290 init(lcd, fact);
291 initEngineID();
292 if(engineid == null)
293 engineid = SnmpEngineId.createEngineId();
294
295 lcd.storeEngineId(engineid);
296
297 if (SNMP_LOGGER.isLoggable(Level.FINER)) {
298 SNMP_LOGGER.logp(Level.FINER, SnmpEngineImpl.class.getName(),
299 "SnmpEngineImpl(SnmpEngineFactory,SnmpLcd)",
300 "LOCAL ENGINE ID: " + engineid + " / " +
301 "LOCAL ENGINE NB BOOTS: " + boot + " / " +
302 "LOCAL ENGINE START TIME: " + getEngineTime());
303 }
304 }
305
306 /**
307 * Access Control will check the oids. By default is false.
308 */
309 public synchronized void activateCheckOid() {
310 checkOid = true;
311 }
312
313 /**
314 * Access Control will not check the oids. By default is false.
315 */
316 public synchronized void deactivateCheckOid() {
317 checkOid = false;
318 }
319
320 /**
321 * Access Control check or not the oids. By default is false.
322 */
323 public synchronized boolean isCheckOidActivated() {
324 return checkOid;
325 }
326
327 //Do some check and store the nb boots value.
328 private void storeNBBoots(int boot) {
329 if(boot < 0 || boot == 0x7FFFFFFF) {
330 boot = 0x7FFFFFFF;
331 lcd.storeEngineBoots(boot);
332 }
333 else
334 lcd.storeEngineBoots(boot + 1);
335 }
336
337 // Initialize internal status.
338 private void init(SnmpLcd lcd, SnmpEngineFactory fact) {
339 this.factory = fact;
340 this.lcd = lcd;
341 boot = lcd.getEngineBoots();
342
343 if(boot == -1 || boot == 0)
344 boot = 1;
345
346 storeNBBoots(boot);
347
348 startTime = System.currentTimeMillis() / 1000;
349
350 }
351
352 void setUsmKeyHandler(SnmpUsmKeyHandler usmKeyHandler) {
353 this.usmKeyHandler = usmKeyHandler;
354 }
355
356 //Initialize the engineID.
357 private void initEngineID() throws UnknownHostException {
358 String id = lcd.getEngineId();
359 if(id != null) {
360 engineid = SnmpEngineId.createEngineId(id);
361 }
362 }
363
364
365 /**
366 * Returns the Message Processing Sub System.
367 * @return The Message Processing Sub System.
368 */
369 public SnmpMsgProcessingSubSystem getMsgProcessingSubSystem() {
370 return messageSub;
371 }
372
373 /**
374 * Sets the Message Processing Sub System.
375 * @param sys The Message Processing Sub System.
376 */
377 public void setMsgProcessingSubSystem(SnmpMsgProcessingSubSystem sys) {
378 messageSub = sys;
379 }
380
381 /**
382 * Returns the Security Sub System.
383 * @return The Security Sub System.
384 */
385 public SnmpSecuritySubSystem getSecuritySubSystem() {
386 return securitySub;
387 }
388 /**
389 * Sets the Security Sub System.
390 * @param sys The Security Sub System.
391 */
392 public void setSecuritySubSystem(SnmpSecuritySubSystem sys) {
393 securitySub = sys;
394 }
395 /**
396 * Sets the Access Control Sub System.
397 * @param sys The Access Control Sub System.
398 */
399 public void setAccessControlSubSystem(SnmpAccessControlSubSystem sys) {
400 accessSub = sys;
401 }
402
403 /**
404 * Returns the Access Control Sub System.
405 * @return The Access Control Sub System.
406 */
407 public SnmpAccessControlSubSystem getAccessControlSubSystem() {
408 return accessSub;
409 }
410 /**
411 * Checks the passed msg flags according to the rules specified in RFC 2572.
412 * @param msgFlags The msg flags.
413 */
414 public static void checkSecurityLevel(byte msgFlags)
415 throws SnmpBadSecurityLevelException {
416 int secLevel = msgFlags & SnmpDefinitions.authPriv;
417 if((secLevel & SnmpDefinitions.privMask) != 0)
418 if((secLevel & SnmpDefinitions.authMask) == 0) {
419 throw new SnmpBadSecurityLevelException("Security level:"+
420 " noAuthPriv!!!");
421 }
422 }
423
424}