1 /* |
|
2 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 * or visit www.oracle.com if you need additional information or have any |
|
23 * questions. |
|
24 */ |
|
25 |
|
26 |
|
27 package com.sun.jmx.snmp.daemon; |
|
28 |
|
29 |
|
30 |
|
31 // java import |
|
32 // |
|
33 import java.util.Vector; |
|
34 import java.util.Enumeration; |
|
35 import java.util.Hashtable; |
|
36 import java.util.logging.Level; |
|
37 import java.io.InterruptedIOException; |
|
38 import java.net.DatagramSocket; |
|
39 import java.net.DatagramPacket; |
|
40 import java.net.SocketException; |
|
41 |
|
42 // jmx imports |
|
43 // |
|
44 import javax.management.MBeanServer; |
|
45 import javax.management.ObjectName; |
|
46 import com.sun.jmx.snmp.SnmpMessage; |
|
47 import com.sun.jmx.snmp.SnmpPduFactory; |
|
48 import com.sun.jmx.snmp.SnmpPduBulk; |
|
49 import com.sun.jmx.snmp.SnmpPduPacket; |
|
50 import com.sun.jmx.snmp.SnmpPduRequest; |
|
51 import com.sun.jmx.snmp.SnmpPduTrap; |
|
52 import com.sun.jmx.snmp.SnmpValue; |
|
53 import com.sun.jmx.snmp.SnmpVarBind; |
|
54 import com.sun.jmx.snmp.SnmpVarBindList; |
|
55 import com.sun.jmx.snmp.SnmpDefinitions; |
|
56 import com.sun.jmx.snmp.SnmpStatusException; |
|
57 import com.sun.jmx.snmp.SnmpTooBigException; |
|
58 import com.sun.jmx.snmp.SnmpDataTypeEnums; |
|
59 |
|
60 // RI imports |
|
61 // |
|
62 import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER; |
|
63 |
|
64 // SNMP runtime import |
|
65 // |
|
66 import com.sun.jmx.snmp.agent.SnmpMibAgent; |
|
67 import com.sun.jmx.snmp.agent.SnmpUserDataFactory; |
|
68 //import com.sun.jmx.snmp.IPAcl.IPAcl; |
|
69 import com.sun.jmx.snmp.InetAddressAcl; |
|
70 |
|
71 |
|
72 class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { |
|
73 |
|
74 private transient DatagramSocket socket = null ; |
|
75 private transient DatagramPacket packet = null ; |
|
76 private transient Vector<SnmpMibAgent> mibs = null ; |
|
77 |
|
78 /** |
|
79 * Contains the list of sub-requests associated to the current request. |
|
80 */ |
|
81 private transient Hashtable<SnmpMibAgent, SnmpSubRequestHandler> subs = null; |
|
82 |
|
83 /** |
|
84 * Reference on the MIBS |
|
85 */ |
|
86 private transient SnmpMibTree root; |
|
87 |
|
88 private transient InetAddressAcl ipacl = null ; |
|
89 private transient SnmpPduFactory pduFactory = null ; |
|
90 private transient SnmpUserDataFactory userDataFactory = null ; |
|
91 private transient SnmpAdaptorServer adaptor = null; |
|
92 /** |
|
93 * Full constructor |
|
94 */ |
|
95 public SnmpRequestHandler(SnmpAdaptorServer server, int id, |
|
96 DatagramSocket s, DatagramPacket p, |
|
97 SnmpMibTree tree, Vector<SnmpMibAgent> m, |
|
98 InetAddressAcl a, |
|
99 SnmpPduFactory factory, |
|
100 SnmpUserDataFactory dataFactory, |
|
101 MBeanServer f, ObjectName n) |
|
102 { |
|
103 super(server, id, f, n); |
|
104 |
|
105 // Need a reference on SnmpAdaptorServer for getNext & getBulk, |
|
106 // in case of oid equality (mib overlapping). |
|
107 // |
|
108 adaptor = server; |
|
109 socket = s; |
|
110 packet = p; |
|
111 root= tree; |
|
112 mibs = new Vector<>(m); |
|
113 subs= new Hashtable<>(mibs.size()); |
|
114 ipacl = a; |
|
115 pduFactory = factory ; |
|
116 userDataFactory = dataFactory ; |
|
117 //thread.start(); |
|
118 } |
|
119 |
|
120 /** |
|
121 * Treat the request available in 'packet' and send the result |
|
122 * back to the client. |
|
123 * Note: we overwrite 'packet' with the response bytes. |
|
124 */ |
|
125 @Override |
|
126 public void doRun() { |
|
127 |
|
128 // Trace the input packet |
|
129 // |
|
130 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
|
131 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
|
132 "doRun","Packet received:\n" + |
|
133 SnmpMessage.dumpHexBuffer(packet.getData(), 0, packet.getLength())); |
|
134 } |
|
135 |
|
136 // Let's build the response packet |
|
137 // |
|
138 DatagramPacket respPacket = makeResponsePacket(packet) ; |
|
139 |
|
140 // Trace the output packet |
|
141 // |
|
142 if ((SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) && (respPacket != null)) { |
|
143 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
|
144 "doRun","Packet to be sent:\n" + |
|
145 SnmpMessage.dumpHexBuffer(respPacket.getData(), 0, respPacket.getLength())); |
|
146 } |
|
147 |
|
148 // Send the response packet if any |
|
149 // |
|
150 if (respPacket != null) { |
|
151 try { |
|
152 socket.send(respPacket) ; |
|
153 } catch (SocketException e) { |
|
154 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
155 if (e.getMessage().equals(InterruptSysCallMsg)) { |
|
156 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
157 "doRun", "interrupted"); |
|
158 } else { |
|
159 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
160 "doRun", "I/O exception", e); |
|
161 } |
|
162 } |
|
163 } catch(InterruptedIOException e) { |
|
164 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
165 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
166 "doRun", "interrupted"); |
|
167 } |
|
168 } catch(Exception e) { |
|
169 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
170 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
171 "doRun", "failure when sending response", e); |
|
172 } |
|
173 } |
|
174 } |
|
175 } |
|
176 |
|
177 /** |
|
178 * Here we make a response packet from a request packet. |
|
179 * We return null if there no response packet to sent. |
|
180 */ |
|
181 private DatagramPacket makeResponsePacket(DatagramPacket reqPacket) { |
|
182 DatagramPacket respPacket = null ; |
|
183 |
|
184 // Transform the request packet into a request SnmpMessage |
|
185 // |
|
186 SnmpMessage reqMsg = new SnmpMessage() ; |
|
187 try { |
|
188 reqMsg.decodeMessage(reqPacket.getData(), reqPacket.getLength()) ; |
|
189 reqMsg.address = reqPacket.getAddress() ; |
|
190 reqMsg.port = reqPacket.getPort() ; |
|
191 } |
|
192 catch(SnmpStatusException x) { |
|
193 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
194 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
195 "makeResponsePacket", "packet decoding failed", x); |
|
196 } |
|
197 reqMsg = null ; |
|
198 ((SnmpAdaptorServer)adaptorServer).incSnmpInASNParseErrs(1) ; |
|
199 } |
|
200 |
|
201 // Make the response SnmpMessage if any |
|
202 // |
|
203 SnmpMessage respMsg = null ; |
|
204 if (reqMsg != null) { |
|
205 respMsg = makeResponseMessage(reqMsg) ; |
|
206 } |
|
207 |
|
208 // Try to transform the response SnmpMessage into response packet. |
|
209 // NOTE: we overwrite the request packet. |
|
210 // |
|
211 if (respMsg != null) { |
|
212 try { |
|
213 reqPacket.setLength(respMsg.encodeMessage(reqPacket.getData())) ; |
|
214 respPacket = reqPacket ; |
|
215 } |
|
216 catch(SnmpTooBigException x) { |
|
217 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
218 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
219 "makeResponsePacket", "response message is too big"); |
|
220 } |
|
221 try { |
|
222 respMsg = newTooBigMessage(reqMsg) ; |
|
223 reqPacket.setLength(respMsg.encodeMessage(reqPacket.getData())) ; |
|
224 respPacket = reqPacket ; |
|
225 } |
|
226 catch(SnmpTooBigException xx) { |
|
227 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
228 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
229 "makeResponsePacket", "'too big' is 'too big' !!!"); |
|
230 } |
|
231 adaptor.incSnmpSilentDrops(1); |
|
232 } |
|
233 } |
|
234 } |
|
235 |
|
236 return respPacket ; |
|
237 } |
|
238 |
|
239 /** |
|
240 * Here we make a response message from a request message. |
|
241 * We return null if there is no message to reply. |
|
242 */ |
|
243 private SnmpMessage makeResponseMessage(SnmpMessage reqMsg) { |
|
244 SnmpMessage respMsg = null ; |
|
245 |
|
246 // Transform the request message into a request pdu |
|
247 // |
|
248 SnmpPduPacket reqPdu; |
|
249 Object userData = null; |
|
250 try { |
|
251 reqPdu = (SnmpPduPacket)pduFactory.decodeSnmpPdu(reqMsg) ; |
|
252 if (reqPdu != null && userDataFactory != null) |
|
253 userData = userDataFactory.allocateUserData(reqPdu); |
|
254 } |
|
255 catch(SnmpStatusException x) { |
|
256 reqPdu = null ; |
|
257 SnmpAdaptorServer snmpServer = (SnmpAdaptorServer)adaptorServer ; |
|
258 snmpServer.incSnmpInASNParseErrs(1) ; |
|
259 if (x.getStatus()== SnmpDefinitions.snmpWrongSnmpVersion) |
|
260 snmpServer.incSnmpInBadVersions(1) ; |
|
261 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
262 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
263 "makeResponseMessage", "message decoding failed", x); |
|
264 } |
|
265 } |
|
266 |
|
267 // Make the response pdu if any |
|
268 // |
|
269 SnmpPduPacket respPdu = null ; |
|
270 if (reqPdu != null) { |
|
271 respPdu = makeResponsePdu(reqPdu,userData) ; |
|
272 try { |
|
273 if (userDataFactory != null) |
|
274 userDataFactory.releaseUserData(userData,respPdu); |
|
275 } catch (SnmpStatusException x) { |
|
276 respPdu = null; |
|
277 } |
|
278 } |
|
279 |
|
280 // Try to transform the response pdu into a response message if any |
|
281 // |
|
282 if (respPdu != null) { |
|
283 try { |
|
284 respMsg = (SnmpMessage)pduFactory. |
|
285 encodeSnmpPdu(respPdu, packet.getData().length) ; |
|
286 } |
|
287 catch(SnmpStatusException x) { |
|
288 respMsg = null ; |
|
289 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
290 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
291 "makeResponseMessage", "failure when encoding the response message", x); |
|
292 } |
|
293 } |
|
294 catch(SnmpTooBigException x) { |
|
295 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
296 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
297 "makeResponseMessage", "response message is too big"); |
|
298 } |
|
299 |
|
300 try { |
|
301 // if the PDU is too small, why should we try to do |
|
302 // recovery ? |
|
303 // |
|
304 if (packet.getData().length <=32) |
|
305 throw x; |
|
306 int pos= x.getVarBindCount(); |
|
307 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
308 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
309 "makeResponseMessage", "fail on element" + pos); |
|
310 } |
|
311 int old; |
|
312 while (true) { |
|
313 try { |
|
314 respPdu = reduceResponsePdu(reqPdu, respPdu, pos) ; |
|
315 respMsg = (SnmpMessage)pduFactory. |
|
316 encodeSnmpPdu(respPdu, |
|
317 packet.getData().length -32) ; |
|
318 break; |
|
319 } catch (SnmpTooBigException xx) { |
|
320 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
321 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
322 "makeResponseMessage", "response message is still too big"); |
|
323 } |
|
324 old= pos; |
|
325 pos= xx.getVarBindCount(); |
|
326 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
327 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
328 "makeResponseMessage","fail on element" + pos); |
|
329 } |
|
330 if (pos == old) { |
|
331 // we can not go any further in trying to |
|
332 // reduce the message ! |
|
333 // |
|
334 throw xx; |
|
335 } |
|
336 } |
|
337 }// end of loop |
|
338 } catch(SnmpStatusException xx) { |
|
339 respMsg = null ; |
|
340 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
341 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
342 "makeResponseMessage", "failure when encoding the response message", xx); |
|
343 } |
|
344 } |
|
345 catch(SnmpTooBigException xx) { |
|
346 try { |
|
347 respPdu = newTooBigPdu(reqPdu) ; |
|
348 respMsg = (SnmpMessage)pduFactory. |
|
349 encodeSnmpPdu(respPdu, packet.getData().length) ; |
|
350 } |
|
351 catch(SnmpTooBigException xxx) { |
|
352 respMsg = null ; |
|
353 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
354 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
355 "makeResponseMessage", "'too big' is 'too big' !!!"); |
|
356 } |
|
357 adaptor.incSnmpSilentDrops(1); |
|
358 } |
|
359 catch(Exception xxx) { |
|
360 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
361 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
362 "makeResponseMessage", "Got unexpected exception", xxx); |
|
363 } |
|
364 respMsg = null ; |
|
365 } |
|
366 } |
|
367 catch(Exception xx) { |
|
368 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
369 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
370 "makeResponseMessage", "Got unexpected exception", xx); |
|
371 } |
|
372 respMsg = null ; |
|
373 } |
|
374 } |
|
375 } |
|
376 return respMsg ; |
|
377 } |
|
378 |
|
379 /** |
|
380 * Here we make a response pdu from a request pdu. |
|
381 * We return null if there is no pdu to reply. |
|
382 */ |
|
383 private SnmpPduPacket makeResponsePdu(SnmpPduPacket reqPdu, |
|
384 Object userData) { |
|
385 |
|
386 SnmpAdaptorServer snmpServer = (SnmpAdaptorServer)adaptorServer ; |
|
387 SnmpPduPacket respPdu = null ; |
|
388 |
|
389 snmpServer.updateRequestCounters(reqPdu.type) ; |
|
390 if (reqPdu.varBindList != null) |
|
391 snmpServer.updateVarCounters(reqPdu.type, |
|
392 reqPdu.varBindList.length) ; |
|
393 |
|
394 if (checkPduType(reqPdu)) { |
|
395 respPdu = checkAcl(reqPdu) ; |
|
396 if (respPdu == null) { // reqPdu is accepted by ACLs |
|
397 if (mibs.size() < 1) { |
|
398 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
|
399 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
|
400 "makeResponsePdu", "Request " + reqPdu.requestId + |
|
401 " received but no MIB registered."); |
|
402 } |
|
403 return makeNoMibErrorPdu((SnmpPduRequest)reqPdu, userData); |
|
404 } |
|
405 switch(reqPdu.type) { |
|
406 case SnmpPduPacket.pduGetRequestPdu: |
|
407 case SnmpPduPacket.pduGetNextRequestPdu: |
|
408 case SnmpPduPacket.pduSetRequestPdu: |
|
409 respPdu = makeGetSetResponsePdu((SnmpPduRequest)reqPdu, |
|
410 userData) ; |
|
411 break ; |
|
412 |
|
413 case SnmpPduPacket.pduGetBulkRequestPdu: |
|
414 respPdu = makeGetBulkResponsePdu((SnmpPduBulk)reqPdu, |
|
415 userData) ; |
|
416 break ; |
|
417 } |
|
418 } |
|
419 else { // reqPdu is rejected by ACLs |
|
420 // respPdu contains the error response to be sent. |
|
421 // We send this response only if authResEnabled is true. |
|
422 if (!snmpServer.getAuthRespEnabled()) { // No response should be sent |
|
423 respPdu = null ; |
|
424 } |
|
425 if (snmpServer.getAuthTrapEnabled()) { // A trap must be sent |
|
426 try { |
|
427 snmpServer.snmpV1Trap(SnmpPduTrap. |
|
428 trapAuthenticationFailure, 0, |
|
429 new SnmpVarBindList()) ; |
|
430 } |
|
431 catch(Exception x) { |
|
432 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
433 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
434 "makeResponsePdu", "Failure when sending authentication trap", x); |
|
435 } |
|
436 } |
|
437 } |
|
438 } |
|
439 } |
|
440 return respPdu ; |
|
441 } |
|
442 |
|
443 // |
|
444 // Generates a response packet, filling the values in the |
|
445 // varbindlist with one of endOfMibView, noSuchObject, noSuchInstance |
|
446 // according to the value of <code>status</code> |
|
447 // |
|
448 // @param statusTag should be one of: |
|
449 // <li>SnmpDataTypeEnums.errEndOfMibViewTag</li> |
|
450 // <li>SnmpDataTypeEnums.errNoSuchObjectTag</li> |
|
451 // <li>SnmpDataTypeEnums.errNoSuchInstanceTag</li> |
|
452 // |
|
453 SnmpPduPacket makeErrorVarbindPdu(SnmpPduPacket req, int statusTag) { |
|
454 |
|
455 final SnmpVarBind[] vblist = req.varBindList; |
|
456 final int length = vblist.length; |
|
457 |
|
458 switch (statusTag) { |
|
459 case SnmpDataTypeEnums.errEndOfMibViewTag: |
|
460 for (int i=0 ; i<length ; i++) |
|
461 vblist[i].value = SnmpVarBind.endOfMibView; |
|
462 break; |
|
463 case SnmpDataTypeEnums.errNoSuchObjectTag: |
|
464 for (int i=0 ; i<length ; i++) |
|
465 vblist[i].value = SnmpVarBind.noSuchObject; |
|
466 break; |
|
467 case SnmpDataTypeEnums.errNoSuchInstanceTag: |
|
468 for (int i=0 ; i<length ; i++) |
|
469 vblist[i].value = SnmpVarBind.noSuchInstance; |
|
470 break; |
|
471 default: |
|
472 return newErrorResponsePdu(req,snmpRspGenErr,1); |
|
473 } |
|
474 return newValidResponsePdu(req,vblist); |
|
475 } |
|
476 |
|
477 // Generates an appropriate response when no mib is registered in |
|
478 // the adaptor. |
|
479 // |
|
480 // <li>If the version is V1:</li> |
|
481 // <ul><li>Generates a NoSuchName error V1 response PDU</li></ul> |
|
482 // <li>If the version is V2:</li> |
|
483 // <ul><li>If the request is a GET, fills the varbind list with |
|
484 // NoSuchObject's</li> |
|
485 // <li>If the request is a GET-NEXT/GET-BULK, fills the varbind |
|
486 // list with EndOfMibView's</li> |
|
487 // <li>If the request is a SET, generates a NoAccess error V2 |
|
488 // response PDU</li> |
|
489 // </ul> |
|
490 // |
|
491 // |
|
492 SnmpPduPacket makeNoMibErrorPdu(SnmpPduRequest req, Object userData) { |
|
493 // There is no agent registered |
|
494 // |
|
495 if (req.version == SnmpDefinitions.snmpVersionOne) { |
|
496 // Version 1: => NoSuchName |
|
497 return |
|
498 newErrorResponsePdu(req,snmpRspNoSuchName,1); |
|
499 } else if (req.version == SnmpDefinitions.snmpVersionTwo) { |
|
500 // Version 2: => depends on PDU type |
|
501 switch (req.type) { |
|
502 case pduSetRequestPdu : |
|
503 case pduWalkRequest : |
|
504 // SET request => NoAccess |
|
505 return |
|
506 newErrorResponsePdu(req,snmpRspNoAccess,1); |
|
507 case pduGetRequestPdu : |
|
508 // GET request => NoSuchObject |
|
509 return |
|
510 makeErrorVarbindPdu(req,SnmpDataTypeEnums. |
|
511 errNoSuchObjectTag); |
|
512 case pduGetNextRequestPdu : |
|
513 case pduGetBulkRequestPdu : |
|
514 // GET-NEXT or GET-BULK => EndOfMibView |
|
515 return |
|
516 makeErrorVarbindPdu(req,SnmpDataTypeEnums. |
|
517 errEndOfMibViewTag); |
|
518 default: |
|
519 } |
|
520 } |
|
521 // Something wrong here: => snmpRspGenErr |
|
522 return newErrorResponsePdu(req,snmpRspGenErr,1); |
|
523 } |
|
524 |
|
525 /** |
|
526 * Here we make the response pdu from a get/set request pdu. |
|
527 * At this level, the result is never null. |
|
528 */ |
|
529 private SnmpPduPacket makeGetSetResponsePdu(SnmpPduRequest req, |
|
530 Object userData) { |
|
531 |
|
532 // Create the trhead group specific for handling sub-requests |
|
533 // associated to the current request. Use the invoke id |
|
534 // |
|
535 // Nice idea to use a thread group on a request basis. |
|
536 // However the impact on performance is terrible ! |
|
537 // theGroup= new ThreadGroup(thread.getThreadGroup(), |
|
538 // "request " + String.valueOf(req.requestId)); |
|
539 |
|
540 // Let's build the varBindList for the response pdu |
|
541 // |
|
542 |
|
543 if (req.varBindList == null) { |
|
544 // Good ! Let's make a full response pdu. |
|
545 // |
|
546 return newValidResponsePdu(req, null) ; |
|
547 } |
|
548 |
|
549 // First we need to split the request into subrequests |
|
550 // |
|
551 splitRequest(req); |
|
552 int nbSubRequest= subs.size(); |
|
553 if (nbSubRequest == 1) |
|
554 return turboProcessingGetSet(req,userData); |
|
555 |
|
556 |
|
557 // Execute all the subrequests resulting from the split of the |
|
558 // varbind list. |
|
559 // |
|
560 SnmpPduPacket result= executeSubRequest(req,userData); |
|
561 if (result != null) |
|
562 // It means that an error occurred. The error is already |
|
563 // formatted by the executeSubRequest |
|
564 // method. |
|
565 return result; |
|
566 |
|
567 // So far so good. So we need to concatenate all the answers. |
|
568 // |
|
569 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
|
570 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
|
571 "makeGetSetResponsePdu", |
|
572 "Build the unified response for request " + req.requestId); |
|
573 } |
|
574 return mergeResponses(req); |
|
575 } |
|
576 |
|
577 /** |
|
578 * The method runs all the sub-requests associated to the current |
|
579 * instance of SnmpRequestHandler. |
|
580 */ |
|
581 private SnmpPduPacket executeSubRequest(SnmpPduPacket req, |
|
582 Object userData) { |
|
583 |
|
584 int errorStatus = SnmpDefinitions.snmpRspNoError ; |
|
585 |
|
586 int i; |
|
587 // If it's a set request, we must first check any varBind |
|
588 // |
|
589 if (req.type == pduSetRequestPdu) { |
|
590 |
|
591 i=0; |
|
592 for(Enumeration<SnmpSubRequestHandler> e= subs.elements(); e.hasMoreElements() ; i++) { |
|
593 // Indicate to the sub request that a check must be invoked ... |
|
594 // OK we should have defined out own tag for that ! |
|
595 // |
|
596 SnmpSubRequestHandler sub= e.nextElement(); |
|
597 sub.setUserData(userData); |
|
598 sub.type= pduWalkRequest; |
|
599 |
|
600 sub.run(); |
|
601 |
|
602 sub.type= pduSetRequestPdu; |
|
603 |
|
604 if (sub.getErrorStatus() != SnmpDefinitions.snmpRspNoError) { |
|
605 // No point to go any further. |
|
606 // |
|
607 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
608 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
609 "executeSubRequest", "an error occurs"); |
|
610 } |
|
611 |
|
612 return newErrorResponsePdu(req, errorStatus, |
|
613 sub.getErrorIndex() + 1) ; |
|
614 } |
|
615 } |
|
616 }// end processing check operation for a set PDU. |
|
617 |
|
618 // Let's start the sub-requests. |
|
619 // |
|
620 i=0; |
|
621 for(Enumeration<SnmpSubRequestHandler> e= subs.elements(); e.hasMoreElements() ;i++) { |
|
622 SnmpSubRequestHandler sub= e.nextElement(); |
|
623 /* NPCTE fix for bugId 4492741, esc 0, 16-August 2001 */ |
|
624 sub.setUserData(userData); |
|
625 /* end of NPCTE fix for bugId 4492741 */ |
|
626 |
|
627 sub.run(); |
|
628 |
|
629 if (sub.getErrorStatus() != SnmpDefinitions.snmpRspNoError) { |
|
630 // No point to go any further. |
|
631 // |
|
632 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
633 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
634 "executeSubRequest", "an error occurs"); |
|
635 } |
|
636 |
|
637 return newErrorResponsePdu(req, errorStatus, |
|
638 sub.getErrorIndex() + 1) ; |
|
639 } |
|
640 } |
|
641 |
|
642 // everything is ok |
|
643 // |
|
644 return null; |
|
645 } |
|
646 |
|
647 /** |
|
648 * Optimize when there is only one sub request |
|
649 */ |
|
650 private SnmpPduPacket turboProcessingGetSet(SnmpPduRequest req, |
|
651 Object userData) { |
|
652 |
|
653 int errorStatus; |
|
654 SnmpSubRequestHandler sub = subs.elements().nextElement(); |
|
655 sub.setUserData(userData); |
|
656 |
|
657 // Indicate to the sub request that a check must be invoked ... |
|
658 // OK we should have defined out own tag for that ! |
|
659 // |
|
660 if (req.type == SnmpDefinitions.pduSetRequestPdu) { |
|
661 sub.type= pduWalkRequest; |
|
662 sub.run(); |
|
663 sub.type= pduSetRequestPdu; |
|
664 |
|
665 // Check the error status. |
|
666 // |
|
667 errorStatus= sub.getErrorStatus(); |
|
668 if (errorStatus != SnmpDefinitions.snmpRspNoError) { |
|
669 // No point to go any further. |
|
670 // |
|
671 return newErrorResponsePdu(req, errorStatus, |
|
672 sub.getErrorIndex() + 1) ; |
|
673 } |
|
674 } |
|
675 |
|
676 // process the operation |
|
677 // |
|
678 |
|
679 sub.run(); |
|
680 errorStatus= sub.getErrorStatus(); |
|
681 if (errorStatus != SnmpDefinitions.snmpRspNoError) { |
|
682 // No point to go any further. |
|
683 // |
|
684 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
685 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
686 "turboProcessingGetSet", "an error occurs"); |
|
687 } |
|
688 int realIndex= sub.getErrorIndex() + 1; |
|
689 return newErrorResponsePdu(req, errorStatus, realIndex) ; |
|
690 } |
|
691 |
|
692 // So far so good. So we need to concatenate all the answers. |
|
693 // |
|
694 |
|
695 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
|
696 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
|
697 "turboProcessingGetSet", "build the unified response for request " |
|
698 + req.requestId); |
|
699 } |
|
700 return mergeResponses(req); |
|
701 } |
|
702 |
|
703 /** |
|
704 * Here we make the response pdu for a bulk request. |
|
705 * At this level, the result is never null. |
|
706 */ |
|
707 private SnmpPduPacket makeGetBulkResponsePdu(SnmpPduBulk req, |
|
708 Object userData) { |
|
709 |
|
710 SnmpVarBind[] respVarBindList; |
|
711 |
|
712 // RFC 1905, Section 4.2.3, p14 |
|
713 int L = req.varBindList.length ; |
|
714 int N = Math.max(Math.min(req.nonRepeaters, L), 0) ; |
|
715 int M = Math.max(req.maxRepetitions, 0) ; |
|
716 int R = L - N ; |
|
717 |
|
718 if (req.varBindList == null) { |
|
719 // Good ! Let's make a full response pdu. |
|
720 // |
|
721 return newValidResponsePdu(req, null) ; |
|
722 } |
|
723 |
|
724 // Split the request into subrequests. |
|
725 // |
|
726 splitBulkRequest(req, N, M, R); |
|
727 SnmpPduPacket result= executeSubRequest(req,userData); |
|
728 if (result != null) |
|
729 return result; |
|
730 |
|
731 respVarBindList= mergeBulkResponses(N + (M * R)); |
|
732 |
|
733 // Now we remove useless trailing endOfMibView. |
|
734 // |
|
735 int m2 ; // respVarBindList[m2] item and next are going to be removed |
|
736 int t = respVarBindList.length ; |
|
737 while ((t > N) && (respVarBindList[t-1]. |
|
738 value.equals(SnmpVarBind.endOfMibView))) { |
|
739 t-- ; |
|
740 } |
|
741 if (t == N) |
|
742 m2 = N + R ; |
|
743 else |
|
744 m2 = N + ((t -1 -N) / R + 2) * R ; // Trivial, of course... |
|
745 if (m2 < respVarBindList.length) { |
|
746 SnmpVarBind[] truncatedList = new SnmpVarBind[m2] ; |
|
747 for (int i = 0 ; i < m2 ; i++) { |
|
748 truncatedList[i] = respVarBindList[i] ; |
|
749 } |
|
750 respVarBindList = truncatedList ; |
|
751 } |
|
752 |
|
753 // Good ! Let's make a full response pdu. |
|
754 // |
|
755 return newValidResponsePdu(req, respVarBindList) ; |
|
756 } |
|
757 |
|
758 /** |
|
759 * Check the type of the pdu: only the get/set/bulk request |
|
760 * are accepted. |
|
761 */ |
|
762 private boolean checkPduType(SnmpPduPacket pdu) { |
|
763 |
|
764 boolean result; |
|
765 |
|
766 switch(pdu.type) { |
|
767 |
|
768 case SnmpDefinitions.pduGetRequestPdu: |
|
769 case SnmpDefinitions.pduGetNextRequestPdu: |
|
770 case SnmpDefinitions.pduSetRequestPdu: |
|
771 case SnmpDefinitions.pduGetBulkRequestPdu: |
|
772 result = true ; |
|
773 break; |
|
774 |
|
775 default: |
|
776 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
777 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
778 "checkPduType", "cannot respond to this kind of PDU"); |
|
779 } |
|
780 result = false ; |
|
781 break; |
|
782 } |
|
783 |
|
784 return result ; |
|
785 } |
|
786 |
|
787 /** |
|
788 * Check if the specified pdu is conform to the ACL. |
|
789 * This method returns null if the pdu is ok. If not, it returns |
|
790 * the response pdu to be replied. |
|
791 */ |
|
792 private SnmpPduPacket checkAcl(SnmpPduPacket pdu) { |
|
793 SnmpPduPacket response = null ; |
|
794 String community = new String(pdu.community) ; |
|
795 |
|
796 // We check the pdu type and create an error response if |
|
797 // the check failed. |
|
798 // |
|
799 if (ipacl != null) { |
|
800 if (pdu.type == SnmpDefinitions.pduSetRequestPdu) { |
|
801 if (!ipacl.checkWritePermission(pdu.address, community)) { |
|
802 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
|
803 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
|
804 "checkAcl", "sender is " + pdu.address + |
|
805 " with " + community +". Sender has no write permission"); |
|
806 } |
|
807 int err = SnmpSubRequestHandler. |
|
808 mapErrorStatus(SnmpDefinitions. |
|
809 snmpRspAuthorizationError, |
|
810 pdu.version, pdu.type); |
|
811 response = newErrorResponsePdu(pdu, err, 0) ; |
|
812 } |
|
813 else { |
|
814 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
|
815 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
|
816 "checkAcl", "sender is " + pdu.address + |
|
817 " with " + community +". Sender has write permission"); |
|
818 } |
|
819 } |
|
820 } |
|
821 else { |
|
822 if (!ipacl.checkReadPermission(pdu.address, community)) { |
|
823 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
|
824 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
|
825 "checkAcl", "sender is " + pdu.address + |
|
826 " with " + community +". Sender has no read permission"); |
|
827 } |
|
828 int err = SnmpSubRequestHandler. |
|
829 mapErrorStatus(SnmpDefinitions. |
|
830 snmpRspAuthorizationError, |
|
831 pdu.version, pdu.type); |
|
832 response = newErrorResponsePdu(pdu, |
|
833 err, |
|
834 0); |
|
835 SnmpAdaptorServer snmpServer = |
|
836 (SnmpAdaptorServer)adaptorServer; |
|
837 snmpServer.updateErrorCounters(SnmpDefinitions. |
|
838 snmpRspNoSuchName); |
|
839 } |
|
840 else { |
|
841 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
|
842 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
|
843 "checkAcl", "sender is " + pdu.address + |
|
844 " with " + community +". Sender has read permission"); |
|
845 } |
|
846 } |
|
847 } |
|
848 } |
|
849 |
|
850 // If the response is not null, this means the pdu is rejected. |
|
851 // So let's update the statistics. |
|
852 // |
|
853 if (response != null) { |
|
854 SnmpAdaptorServer snmpServer = (SnmpAdaptorServer)adaptorServer ; |
|
855 snmpServer.incSnmpInBadCommunityUses(1) ; |
|
856 if (ipacl.checkCommunity(community) == false) |
|
857 snmpServer.incSnmpInBadCommunityNames(1) ; |
|
858 } |
|
859 |
|
860 return response ; |
|
861 } |
|
862 |
|
863 /** |
|
864 * Make a response pdu with the specified error status and index. |
|
865 * NOTE: the response pdu share its varBindList with the request pdu. |
|
866 */ |
|
867 private SnmpPduRequest newValidResponsePdu(SnmpPduPacket reqPdu, |
|
868 SnmpVarBind[] varBindList) { |
|
869 SnmpPduRequest result = new SnmpPduRequest() ; |
|
870 |
|
871 result.address = reqPdu.address ; |
|
872 result.port = reqPdu.port ; |
|
873 result.version = reqPdu.version ; |
|
874 result.community = reqPdu.community ; |
|
875 result.type = SnmpPduRequest.pduGetResponsePdu ; |
|
876 result.requestId = reqPdu.requestId ; |
|
877 result.errorStatus = SnmpDefinitions.snmpRspNoError ; |
|
878 result.errorIndex = 0 ; |
|
879 result.varBindList = varBindList ; |
|
880 |
|
881 ((SnmpAdaptorServer)adaptorServer). |
|
882 updateErrorCounters(result.errorStatus) ; |
|
883 |
|
884 return result ; |
|
885 } |
|
886 |
|
887 /** |
|
888 * Make a response pdu with the specified error status and index. |
|
889 * NOTE: the response pdu share its varBindList with the request pdu. |
|
890 */ |
|
891 private SnmpPduRequest newErrorResponsePdu(SnmpPduPacket req,int s,int i) { |
|
892 SnmpPduRequest result = newValidResponsePdu(req, null) ; |
|
893 result.errorStatus = s ; |
|
894 result.errorIndex = i ; |
|
895 result.varBindList = req.varBindList ; |
|
896 |
|
897 ((SnmpAdaptorServer)adaptorServer). |
|
898 updateErrorCounters(result.errorStatus) ; |
|
899 |
|
900 return result ; |
|
901 } |
|
902 |
|
903 private SnmpMessage newTooBigMessage(SnmpMessage reqMsg) |
|
904 throws SnmpTooBigException { |
|
905 SnmpMessage result = null ; |
|
906 SnmpPduPacket reqPdu; |
|
907 |
|
908 try { |
|
909 reqPdu = (SnmpPduPacket)pduFactory.decodeSnmpPdu(reqMsg) ; |
|
910 if (reqPdu != null) { |
|
911 SnmpPduPacket respPdu = newTooBigPdu(reqPdu) ; |
|
912 result = (SnmpMessage)pduFactory. |
|
913 encodeSnmpPdu(respPdu, packet.getData().length) ; |
|
914 } |
|
915 } |
|
916 catch(SnmpStatusException x) { |
|
917 // This should not occur because decodeIncomingRequest has normally |
|
918 // been successfully called before. |
|
919 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
920 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
921 "newTooBigMessage", "Internal error", x); |
|
922 } |
|
923 throw new InternalError(x) ; |
|
924 } |
|
925 |
|
926 return result ; |
|
927 } |
|
928 |
|
929 private SnmpPduPacket newTooBigPdu(SnmpPduPacket req) { |
|
930 SnmpPduRequest result = |
|
931 newErrorResponsePdu(req, SnmpDefinitions.snmpRspTooBig, 0) ; |
|
932 result.varBindList = null ; |
|
933 return result ; |
|
934 } |
|
935 |
|
936 private SnmpPduPacket reduceResponsePdu(SnmpPduPacket req, |
|
937 SnmpPduPacket resp, |
|
938 int acceptedVbCount) |
|
939 throws SnmpTooBigException { |
|
940 |
|
941 // Reduction can be attempted only on bulk response |
|
942 // |
|
943 if (req.type != SnmpPduPacket.pduGetBulkRequestPdu) { |
|
944 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
945 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
946 "reduceResponsePdu", "cannot remove anything"); |
|
947 } |
|
948 throw new SnmpTooBigException(acceptedVbCount) ; |
|
949 } |
|
950 |
|
951 // We're going to reduce the varbind list. |
|
952 // First determine which items should be removed. |
|
953 // Next duplicate and replace the existing list by the reduced one. |
|
954 // |
|
955 // acceptedVbCount is the number of varbind which have been |
|
956 // successfully encoded before reaching bufferSize: |
|
957 // * when it is >= 2, we split the varbindlist at this |
|
958 // position (-1 to be safe), |
|
959 // * when it is 1, we only put one (big?) item in the varbindlist |
|
960 // * when it is 0 (in fact, acceptedVbCount is not available), |
|
961 // we split the varbindlist by 2. |
|
962 // |
|
963 int vbCount; |
|
964 if (acceptedVbCount >= 3) |
|
965 vbCount = Math.min(acceptedVbCount - 1, resp.varBindList.length) ; |
|
966 else if (acceptedVbCount == 1) |
|
967 vbCount = 1 ; |
|
968 else // acceptedCount == 0 ie it is unknown |
|
969 vbCount = resp.varBindList.length / 2 ; |
|
970 |
|
971 if (vbCount < 1) { |
|
972 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
973 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
974 "reduceResponsePdu", "cannot remove anything"); |
|
975 } |
|
976 throw new SnmpTooBigException(acceptedVbCount) ; |
|
977 } |
|
978 else { |
|
979 SnmpVarBind[] newVbList = new SnmpVarBind[vbCount] ; |
|
980 for (int i = 0 ; i < vbCount ; i++) { |
|
981 newVbList[i] = resp.varBindList[i] ; |
|
982 } |
|
983 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
|
984 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
|
985 "reduceResponsePdu", (resp.varBindList.length - newVbList.length) + |
|
986 " items have been removed"); |
|
987 } |
|
988 resp.varBindList = newVbList ; |
|
989 } |
|
990 |
|
991 return resp ; |
|
992 } |
|
993 |
|
994 /** |
|
995 * The method takes the incoming requests and split it into subrequests. |
|
996 */ |
|
997 private void splitRequest(SnmpPduRequest req) { |
|
998 |
|
999 int nbAgents= mibs.size(); |
|
1000 SnmpMibAgent agent = mibs.firstElement(); |
|
1001 if (nbAgents == 1) { |
|
1002 // Take all the oids contained in the request and |
|
1003 // |
|
1004 subs.put(agent, new SnmpSubRequestHandler(agent, req, true)); |
|
1005 return; |
|
1006 } |
|
1007 |
|
1008 // For the get next operation we are going to send the varbind list |
|
1009 // to all agents |
|
1010 // |
|
1011 if (req.type == pduGetNextRequestPdu) { |
|
1012 for(Enumeration<SnmpMibAgent> e= mibs.elements(); e.hasMoreElements(); ) { |
|
1013 final SnmpMibAgent ag= e.nextElement(); |
|
1014 subs.put(ag, new SnmpSubNextRequestHandler(adaptor, ag, req)); |
|
1015 } |
|
1016 return; |
|
1017 } |
|
1018 |
|
1019 int nbReqs= req.varBindList.length; |
|
1020 SnmpVarBind[] vars= req.varBindList; |
|
1021 SnmpSubRequestHandler sub; |
|
1022 for(int i=0; i < nbReqs; i++) { |
|
1023 agent= root.getAgentMib(vars[i].oid); |
|
1024 sub= subs.get(agent); |
|
1025 if (sub == null) { |
|
1026 // We need to create the sub request handler and update |
|
1027 // the hashtable |
|
1028 // |
|
1029 sub= new SnmpSubRequestHandler(agent, req); |
|
1030 subs.put(agent, sub); |
|
1031 } |
|
1032 |
|
1033 // Update the translation table within the subrequest |
|
1034 // |
|
1035 sub.updateRequest(vars[i], i); |
|
1036 } |
|
1037 } |
|
1038 |
|
1039 /** |
|
1040 * The method takes the incoming get bulk requests and split it into |
|
1041 * subrequests. |
|
1042 */ |
|
1043 private void splitBulkRequest(SnmpPduBulk req, |
|
1044 int nonRepeaters, |
|
1045 int maxRepetitions, |
|
1046 int R) { |
|
1047 // Send the getBulk to all agents |
|
1048 // |
|
1049 for(Enumeration<SnmpMibAgent> e= mibs.elements(); e.hasMoreElements(); ) { |
|
1050 final SnmpMibAgent agent = e.nextElement(); |
|
1051 |
|
1052 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
|
1053 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
|
1054 "splitBulkRequest", "Create a sub with : " + agent + " " + nonRepeaters |
|
1055 + " " + maxRepetitions + " " + R); |
|
1056 } |
|
1057 |
|
1058 subs.put(agent, |
|
1059 new SnmpSubBulkRequestHandler(adaptor, |
|
1060 agent, |
|
1061 req, |
|
1062 nonRepeaters, |
|
1063 maxRepetitions, |
|
1064 R)); |
|
1065 } |
|
1066 } |
|
1067 |
|
1068 private SnmpPduPacket mergeResponses(SnmpPduRequest req) { |
|
1069 |
|
1070 if (req.type == pduGetNextRequestPdu) { |
|
1071 return mergeNextResponses(req); |
|
1072 } |
|
1073 |
|
1074 SnmpVarBind[] result= req.varBindList; |
|
1075 |
|
1076 // Go through the list of subrequests and concatenate. |
|
1077 // Hopefully, by now all the sub-requests should be finished |
|
1078 // |
|
1079 for(Enumeration<SnmpSubRequestHandler> e= subs.elements(); e.hasMoreElements();) { |
|
1080 SnmpSubRequestHandler sub= e.nextElement(); |
|
1081 sub.updateResult(result); |
|
1082 } |
|
1083 return newValidResponsePdu(req,result); |
|
1084 } |
|
1085 |
|
1086 private SnmpPduPacket mergeNextResponses(SnmpPduRequest req) { |
|
1087 int max= req.varBindList.length; |
|
1088 SnmpVarBind[] result= new SnmpVarBind[max]; |
|
1089 |
|
1090 // Go through the list of subrequests and concatenate. |
|
1091 // Hopefully, by now all the sub-requests should be finished |
|
1092 // |
|
1093 for(Enumeration<SnmpSubRequestHandler> e= subs.elements(); e.hasMoreElements();) { |
|
1094 SnmpSubRequestHandler sub= e.nextElement(); |
|
1095 sub.updateResult(result); |
|
1096 } |
|
1097 |
|
1098 if (req.version == snmpVersionTwo) { |
|
1099 return newValidResponsePdu(req,result); |
|
1100 } |
|
1101 |
|
1102 // In v1 make sure there is no endOfMibView ... |
|
1103 // |
|
1104 for(int i=0; i < max; i++) { |
|
1105 SnmpValue val= result[i].value; |
|
1106 if (val == SnmpVarBind.endOfMibView) |
|
1107 return newErrorResponsePdu(req, |
|
1108 SnmpDefinitions.snmpRspNoSuchName, i+1); |
|
1109 } |
|
1110 |
|
1111 // So far so good ... |
|
1112 // |
|
1113 return newValidResponsePdu(req,result); |
|
1114 } |
|
1115 |
|
1116 private SnmpVarBind[] mergeBulkResponses(int size) { |
|
1117 // Let's allocate the array for storing the result |
|
1118 // |
|
1119 SnmpVarBind[] result= new SnmpVarBind[size]; |
|
1120 for(int i= size-1; i >=0; --i) { |
|
1121 result[i]= new SnmpVarBind(); |
|
1122 result[i].value= SnmpVarBind.endOfMibView; |
|
1123 } |
|
1124 |
|
1125 // Go through the list of subrequests and concatenate. |
|
1126 // Hopefully, by now all the sub-requests should be finished |
|
1127 // |
|
1128 for(Enumeration<SnmpSubRequestHandler> e= subs.elements(); e.hasMoreElements();) { |
|
1129 SnmpSubRequestHandler sub= e.nextElement(); |
|
1130 sub.updateResult(result); |
|
1131 } |
|
1132 |
|
1133 return result; |
|
1134 } |
|
1135 |
|
1136 @Override |
|
1137 protected String makeDebugTag() { |
|
1138 return "SnmpRequestHandler[" + adaptorServer.getProtocol() + ":" + |
|
1139 adaptorServer.getPort() + "]"; |
|
1140 } |
|
1141 |
|
1142 @Override |
|
1143 Thread createThread(Runnable r) { |
|
1144 return null; |
|
1145 } |
|
1146 |
|
1147 static final private String InterruptSysCallMsg = |
|
1148 "Interrupted system call"; |
|
1149 } |
|