1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 package uk.co.westhawk.snmp.stack;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 import java.util.*;
66 import java.io.*;
67
68 import uk.co.westhawk.snmp.util.*;
69
70
71
72
73
74
75
76
77 public abstract class Pdu extends Observable {
78 private static final String version_id = "@(#)$Id: Pdu.java,v 3.33 2008/12/12 14:55:51 tpanton Exp $ Copyright Westhawk Ltd";
79
80 protected Vector reqVarbinds = null;
81 protected Vector respVarbinds = null;
82
83 private final static String TIMED_OUT = "Timed out";
84 private final static String[] errorStrings = {
85 "No error",
86 "Value too big error",
87 "No such name error",
88 "Bad value error",
89 "Read only error",
90 "General error",
91 "No access error",
92 "Wrong type error",
93 "Wrong length error",
94 "Wrong encoding error",
95 "Wrong value error",
96 "No creation error",
97 "Inconsistent value error",
98 "Resource unavailable error",
99 "Commit failed error",
100 "Undo failed error",
101 "Authorization error",
102 "Not writable error",
103 "Inconsistent name error",
104 };
105
106 private static int next_id = 1;
107 private static final Object NEXT_ID_LOCK = new Object();
108
109 private int retry_intervals[] = { 500, 1000, 2000, 5000, 5000 };
110
111 protected byte[] encodedPacket = null;
112 protected SnmpContextBasisFace context;
113 protected boolean added = false;
114 protected byte msg_type;
115
116 int req_id;
117 protected Integer snmpv3MsgId = null;
118 protected int errstat;
119 protected int errind;
120
121 private Transmitter trans = null;
122 private int retries;
123 protected boolean answered;
124 private boolean got = false;
125 private boolean isTimedOut;
126 private PduException respException = null;
127
128
129
130
131
132 protected void new_value(int n, varbind res) {
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146 protected void tell_them() {
147 notifyObservers();
148 }
149
150
151
152
153
154
155
156
157
158 public Pdu(SnmpContextBasisFace con) {
159 context = con;
160
161
162
163
164
165
166 synchronized (NEXT_ID_LOCK) {
167 req_id = next_id++;
168 }
169 errstat = AsnObject.SNMP_ERR_NOERROR;
170 errind = 0x00;
171 reqVarbinds = new Vector(1, 1);
172 setMsgType(AsnObject.GET_REQ_MSG);
173 isTimedOut = false;
174
175
176
177 answered = false;
178 }
179
180
181
182
183
184
185 public SnmpContextBasisFace getContext() {
186 return context;
187 }
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204 public void setRetryIntervals(int rinterval[]) {
205 retry_intervals = rinterval;
206 }
207
208 public int[] getRetryIntervals() {
209 return retry_intervals;
210 }
211
212
213
214
215
216
217 public boolean send() throws IOException, PduException {
218 return send(errstat, errind);
219 }
220
221
222
223
224
225
226
227
228 protected boolean send(int error_status, int error_index)
229 throws IOException, PduException {
230 if (added == false) {
231
232
233 added = context.addPdu(this);
234 }
235 Enumeration vbs = reqVarbinds.elements();
236 encodedPacket = context.encodePacket(msg_type, req_id, error_status,
237 error_index, vbs, snmpv3MsgId);
238 addToTrans();
239 return added;
240 }
241
242
243
244
245
246
247
248 protected void addToTrans() {
249 if (added && (trans != null)) {
250
251 synchronized (trans) {
252 trans.setPdu(this);
253 trans.stand();
254 }
255 }
256 }
257
258
259
260
261
262
263 protected boolean sendme() {
264 context.sendPacket(encodedPacket);
265 retries++;
266
267 if (AsnObject.debug > 6) {
268 System.out.println(getClass().getName() + ".sendme(): Sent Pdu reqId=" + req_id + ", retries " + retries);
269 }
270 return (retries > 3);
271 }
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286 public boolean send(String com) throws IOException, PduException {
287 if (context instanceof SnmpContext) {
288 ((SnmpContext) context).setCommunity(com);
289 }
290 return send();
291 }
292
293
294
295
296
297
298
299
300
301 public void addOid(String oid) {
302 varbind vb = new varbind(oid);
303 addOid(vb);
304 }
305
306
307
308
309
310
311
312
313
314
315 public void addOid(AsnObjectId oid) {
316 varbind vb = new varbind(oid);
317 addOid(vb);
318 }
319
320
321
322
323
324
325
326
327
328
329
330 public void addOid(String oid, AsnObject val) {
331 varbind vb = new varbind(oid, val);
332 addOid(vb);
333 }
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349 public void addOid(AsnObjectId oid, AsnObject val) {
350 varbind vb = new varbind(oid, val);
351 addOid(vb);
352 }
353
354
355
356
357
358
359
360 public void addOid(varbind var) {
361 reqVarbinds.addElement(var);
362 }
363
364
365
366
367
368
369 public varbind[] getRequestVarbinds() {
370 int sz = reqVarbinds.size();
371 varbind[] arr = new varbind[sz];
372 reqVarbinds.copyInto(arr);
373 return arr;
374 }
375
376
377
378
379
380
381
382
383
384
385
386
387 public varbind[] getResponseVarbinds() throws PduException {
388 if (respException != null) {
389 throw respException;
390 }
391
392 varbind[] arr = null;
393 if (respVarbinds != null) {
394 int sz = respVarbinds.size();
395 arr = new varbind[sz];
396 respVarbinds.copyInto(arr);
397 }
398 return arr;
399 }
400
401 private void dump(Vector v, varbind[] array) {
402 int sz = v.size();
403 System.out.println("Vector: ");
404 for (int i = 0; i < sz; i++) {
405 System.out.println("\t" + v.elementAt(i));
406 }
407 System.out.println("Array: ");
408 for (int i = 0; i < array.length; i++) {
409 System.out.println("\t" + array[i]);
410 }
411 System.out.println("--");
412 }
413
414 void setResponseException(PduException exc) {
415 if (AsnObject.debug > 6) {
416 System.out.println(getClass().getName() + ".setResponseException(): reqId=" + req_id + exc.getMessage());
417 }
418 respException = exc;
419 }
420
421
422
423
424
425
426 public int getReqId() {
427 return req_id;
428 }
429
430
431
432
433
434
435
436
437 public int getErrorIndex() {
438 return errind;
439 }
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476 public int getErrorStatus() {
477 return errstat;
478 }
479
480
481
482
483
484
485
486 public String getErrorStatusString() {
487 String errString = "";
488 if (errstat >= 0) {
489 if (errstat < errorStrings.length) {
490 errString = errorStrings[errstat];
491
492 if (errstat == AsnObject.SNMP_ERR_GENERR
493 &&
494 isTimedOut() == true) {
495 errString = TIMED_OUT;
496 }
497 } else {
498
499 if (respException != null) {
500 errString = respException.getMessage();
501 } else {
502 errString = "Decoding Exception";
503 }
504 }
505 }
506 return errString;
507 }
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525 public boolean isTimedOut() {
526 return isTimedOut;
527 }
528
529
530
531
532
533 public boolean waitForSelf() {
534
535
536 long del = 1000;
537 for (int i = 0; i < retry_intervals.length; i++) {
538 del += retry_intervals[i];
539 }
540 boolean res = waitForSelf(del);
541
542 if (AsnObject.debug > 6) {
543 System.out.println(getClass().getName() + ".waitForSelf(): reqId=" + req_id + " " + res);
544 }
545
546
547 if (!answered) {
548 handleNoAnswer();
549 }
550
551 return res;
552 }
553
554
555
556
557
558
559 public String toString() {
560 return toString(false);
561 }
562
563
564
565
566
567
568
569
570 protected String toString(boolean withRespVars) {
571 StringBuffer buffer = new StringBuffer(getClass().getName());
572 buffer.append("[");
573 buffer.append("context=").append(context);
574 buffer.append(", reqId=").append(req_id);
575 buffer.append(", msgType=0x").append(SnmpUtilities.toHex(msg_type));
576
577 buffer.append(", ");
578 buffer.append(printVars("reqVarbinds", reqVarbinds));
579
580 if (withRespVars == true) {
581 buffer.append(", ");
582 buffer.append(printVars("respVarbinds", respVarbinds));
583 }
584
585 buffer.append("]");
586 return buffer.toString();
587 }
588
589
590
591
592
593
594
595 protected StringBuffer printVars(String title, Vector vars) {
596 StringBuffer buffer = new StringBuffer();
597 buffer.append(title).append("=");
598 if (vars != null) {
599 int sz = vars.size();
600 buffer.append("[");
601 for (int i = 0; i < sz; i++) {
602 if (i > 0) {
603 buffer.append(", ");
604 }
605 varbind var = (varbind) vars.elementAt(i);
606 buffer.append(var.toString());
607 }
608 buffer.append("]");
609 } else {
610 buffer.append("null");
611 }
612 return buffer;
613 }
614
615 synchronized boolean waitForSelf(long delay) {
616 if (!got) {
617 try {
618 wait(delay);
619 } catch (InterruptedException ix) {
620 ;
621 }
622 }
623 return answered;
624 }
625
626 void transmit() {
627 transmit(true);
628 }
629
630 void transmit(boolean withRetries) {
631 if (withRetries == true) {
632 int n = 0;
633 answered = false;
634
635 while ((!context.isDestroyed()) && (!answered) && (n < retry_intervals.length)) {
636 sendme();
637
638 try {
639 Thread.sleep(retry_intervals[n]);
640 } catch (InterruptedException e) {
641 }
642 n++;
643 }
644
645 if (!answered) {
646 handleNoAnswer();
647 }
648 } else {
649
650
651 sendme();
652 answered = true;
653 }
654
655 if (!context.removePdu(req_id)) {
656 if (AsnObject.debug > 6) {
657 System.out.println(getClass().getName() + ".transmit(): Failed to remove reqId " + req_id);
658 }
659 }
660 }
661
662 void setTrans(Transmitter t) {
663 trans = t;
664 }
665
666
667
668
669
670
671
672
673 public byte getMsgType() {
674 return msg_type;
675 }
676
677
678
679
680
681
682
683
684 protected void setMsgType(byte type) {
685 msg_type = type;
686 }
687
688
689
690
691
692
693
694
695
696 protected void setErrorStatus(int err) {
697 errstat = err;
698 if (AsnObject.debug > 6) {
699 System.out.println(getClass().getName() + ".setErrorStatus(): reqId=" + req_id + " " + errstat);
700 }
701 if (errstat != AsnObject.SNMP_ERR_NOERROR) {
702 setResponseException(new AgentException(getErrorStatusString()));
703 }
704 }
705
706
707
708
709
710
711
712
713
714
715
716 protected void setErrorStatus(int err, PduException exc) {
717 errstat = err;
718 setResponseException(exc);
719 }
720
721
722
723
724
725
726
727
728 protected void setErrorIndex(int ind) {
729 errind = ind;
730 }
731
732
733
734
735
736
737
738
739
740
741
742 protected boolean isExpectingResponse() {
743 return true;
744 }
745
746
747
748
749
750
751
752 private void handleNoAnswer() {
753 if (AsnObject.debug > 6) {
754 System.out.println(getClass().getName() + ".handleNoAnswer(): reqId=" + req_id);
755 }
756
757
758
759 answered = true;
760
761 isTimedOut = true;
762 setErrorStatus(AsnObject.SNMP_ERR_GENERR);
763 setErrorIndex(0);
764
765 setChanged();
766 tell_them();
767 clearChanged();
768
769 synchronized (this) {
770 notify();
771 }
772 }
773
774
775
776
777
778
779
780 void fillin(AsnPduSequence seq) {
781 if (answered) {
782 if (AsnObject.debug > 6) {
783 System.out.println(getClass().getName() + ".fillin(): Got a second answer to reqId " + req_id);
784 }
785 return;
786 }
787
788
789 if (seq != null) {
790 if (seq.isCorrect == true) {
791 int n = -1;
792 try {
793
794 this.req_id = seq.getReqId();
795 setErrorStatus(seq.getWhatError());
796 setErrorIndex(seq.getWhereError());
797
798
799
800 AsnSequence varBind = seq.getVarBind();
801 int size = varBind.getObjCount();
802 respVarbinds = new Vector(size, 1);
803 for (n = 0; n < size; n++) {
804 Object obj = varBind.getObj(n);
805 if (obj instanceof AsnSequence) {
806 AsnSequence varSeq = (AsnSequence) obj;
807 try {
808 varbind vb = new varbind(varSeq);
809 respVarbinds.addElement(vb);
810 new_value(n, vb);
811 } catch (IllegalArgumentException exc) {
812 }
813 }
814 }
815
816
817
818
819
820
821
822 if (reqVarbinds.isEmpty()) {
823 reqVarbinds = (Vector) respVarbinds.clone();
824 }
825 } catch (Exception e) {
826
827
828
829
830 DecodingException exc = new DecodingException(
831 "Incorrect varbind list, element " + n);
832 setErrorStatus(AsnObject.SNMP_ERR_DECODINGASN_EXC, exc);
833 }
834 } else {
835
836
837
838 DecodingException exc = new DecodingException(
839 "Incorrect packet. No of bytes received less than packet length.");
840 setErrorStatus(AsnObject.SNMP_ERR_DECODINGPKTLNGTH_EXC, exc);
841 }
842 }
843
844
845 setChanged();
846 tell_them();
847 clearChanged();
848
849 synchronized (this) {
850 got = true;
851 answered = true;
852 notify();
853 if (trans != null) {
854
855
856
857 trans.interruptMe();
858 }
859 }
860 }
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882 public void notifyObservers(Object arg) {
883 if (respException != null) {
884 super.notifyObservers(respException);
885 } else {
886 super.notifyObservers(arg);
887 }
888 }
889
890 }