ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Net-SNMP-XS/XS.xs
(Generate patch)

Comparing Net-SNMP-XS/XS.xs (file contents):
Revision 1.5 by root, Thu Apr 9 04:49:16 2009 UTC vs.
Revision 1.13 by root, Thu Jul 29 02:52:07 2010 UTC

1#include "EXTERN.h" 1#include "EXTERN.h"
2#include "perl.h" 2#include "perl.h"
3#include "XSUB.h" 3#include "XSUB.h"
4 4
5// C99 required 5// C99 required
6
7//#define BENCHMARK
6 8
7#define ASN_BOOLEAN 0x01 9#define ASN_BOOLEAN 0x01
8#define ASN_INTEGER32 0x02 10#define ASN_INTEGER32 0x02
9#define ASN_OCTET_STRING 0x04 11#define ASN_OCTET_STRING 0x04
10#define ASN_NULL 0x05 12#define ASN_NULL 0x05
15#define ASN_UNSIGNED32 0x42 17#define ASN_UNSIGNED32 0x42
16#define ASN_TIMETICKS 0x43 18#define ASN_TIMETICKS 0x43
17#define ASN_OPAQUE 0x44 19#define ASN_OPAQUE 0x44
18#define ASN_COUNTER64 0x46 20#define ASN_COUNTER64 0x46
19 21
20#define BENCHMARK
21
22#define MAX_OID_STRLEN 4096 22#define MAX_OID_STRLEN 4096
23 23
24#define HAVE_VERSIONSORT defined (_GNU_SOURCE) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
25
26static SV *cur_bufobj;
24static SV *msg; 27static SV *msg, *bufsv;
25static int errflag, leading_dot; 28static int errflag, leading_dot;
26static U8 *buf, *cur; 29static U8 *buf, *cur;
27static STRLEN len, rem; 30static STRLEN len, rem;
28 31
32typedef SV *BUFOBJ;
33
34/////////////////////////////////////////////////////////////////////////////
35
36#if 0
37 if (msg)
38 croak ("recursive invocation of Net::SNMP::XS parser is not supported");
39
40
41void
42clr_msg ()
43 CODE:
44 SvREFCNT_dec (msg); msg = 0;
45 buf = cur = (U8 *)"";
46 len = rem = 0;
47#endif
48
49static void
50clear_bufobj (void)
51{
52 // serialise our state back
53 if (msg && SvROK (msg))
54 {
55 SV *idx_sv = *hv_fetch ((HV *)cur_bufobj, "_index" , sizeof ("_index" ) - 1, 1);
56 sv_setiv (idx_sv, cur - buf);
57
58 SvREFCNT_dec (msg);
59 msg = 0;
60 cur_bufobj = 0;
61 }
62}
63
64static void
65switch_bufobj (BUFOBJ neu)
66{
67 clear_bufobj ();
68
69 msg = newSVsv (neu);
70 cur_bufobj = SvRV (msg);
71 sv_rvweaken (msg);
72
73 errflag = 0;
74 leading_dot = -1;
75
76 IV index = SvIV (*hv_fetch ((HV *)cur_bufobj, "_index" , sizeof ("_index" ) - 1, 1));
77 bufsv = *hv_fetch ((HV *)cur_bufobj, "_buffer", sizeof ("_buffer") - 1, 1);
78
79 buf = SvPVbyte (bufsv, len);
80 cur = buf + index;
81 rem = len - index;
82}
83
84/////////////////////////////////////////////////////////////////////////////
85
29static SV * 86static SV *
30x_get_cv (SV *cb_sv) 87x_get_cv (SV *cb_sv)
31{ 88{
32 HV *st; 89 HV *st;
33 GV *gvp; 90 GV *gvp;
38 95
39 return (SV *)cv; 96 return (SV *)cv;
40} 97}
41 98
42static void 99static void
43error (const char *msg) 100error (const char *errmsg)
44{ 101{
45 errflag = 1; 102 errflag = 1;
46 103
47 printf ("<<<%s>>>\n", msg);//D 104 if (!msg)
105 croak ("Net::SNMP::XS fatal error, parser called without parsing context");
106
107 dSP;
108 PUSHMARK (SP);
109 EXTEND (SP, 2);
110 PUSHs (msg);
111 PUSHs (sv_2mortal (newSVpv (errmsg, 0)));
112 PUTBACK;
113 call_method ("_error", G_VOID | G_DISCARD);
48} 114}
49 115
50static int 116static int
51need (int count) 117need (int count)
52{ 118{
183process_unsigned32_sv (void) 249process_unsigned32_sv (void)
184{ 250{
185 return newSVuv ((U32)process_integer32 ()); 251 return newSVuv ((U32)process_integer32 ());
186} 252}
187 253
254#if IVSIZE >= 8
255
256static U64TYPE
257process_integer64 (void)
258{
259 U32 length = process_length ();
260
261 if (length <= 0)
262 {
263 error ("INTEGER64 length equal to zero");
264 return 0;
265 }
266
267 U8 *data = getn (length, 0);
268
269 if (!data)
270 return 0;
271
272 if (length > 9 || (length > 8 && data [0]))
273 {
274 error ("INTEGER64 length too long");
275 return 0;
276 }
277
278 U64TYPE res = data [0] & 0x80 ? 0xffffffffffffffff : 0;
279
280 while (length--)
281 res = (res << 8) | *data++;
282
283 return res;
284}
285
286static SV *
287process_integer64_sv (void)
288{
289 return newSViv ((I64TYPE)process_integer64 ());
290}
291
292static SV *
293process_unsigned64_sv (void)
294{
295 return newSVuv ((U64TYPE)process_integer64 ());
296}
297
298#endif
299
188static SV * 300static SV *
189process_octet_string_sv (void) 301process_octet_string_sv (void)
190{ 302{
191 U32 length = process_length (); 303 U32 length = process_length ();
192 304
224 } 336 }
225 337
226 U8 *end = cur + length; 338 U8 *end = cur + length;
227 U32 w = getb (); 339 U32 w = getb ();
228 340
229 static char oid[MAX_OID_STRLEN]; 341 static char oid[MAX_OID_STRLEN]; // must be static
230 char *app = oid; 342 char *app = oid;
231 343
344 if (leading_dot < 0)
345 leading_dot = SvTRUE (*hv_fetch ((HV *)SvRV (msg), "_leading_dot", sizeof ("_leading_dot") - 1, 1));
346
232 *app = '.'; app += ! ! leading_dot; 347 *app = '.'; app += ! ! leading_dot;
233 app = write_uv (app, w / 40); 348 app = write_uv (app, (U8)w / 40);
234 *app++ = '.'; 349 *app++ = '.';
235 app = write_uv (app, w % 40); 350 app = write_uv (app, (U8)w % 40);
236 351
237 // we assume an oid component is never > 64 bytes 352 // we assume an oid component is never > 64 bytes
238 while (cur < end && oid + sizeof (oid) - app > 64) 353 while (cur < end && oid + sizeof (oid) - app > 64)
239 { 354 {
240 w = getb (); 355 w = getb ();
241 *app++ = '.'; 356 *app++ = '.';
242 app = write_uv (app, w); 357 app = write_uv (app, w);
243 } 358 }
244#if 0
245 buf += snprintf (buf, oid + sizeof (oid) - buf, "%d.%d", (int)w / 40, (int)w % 40);
246 359
247 while (cur < end) 360 return newSVpvn (oid, app - oid);
248 { 361}
249 w = getb (); 362
250 buf += snprintf (buf, oid + sizeof (oid) - buf, ".%u", (unsigned int)w); 363static AV *av_type;
364
365static SV *
366process_sv (int *found)
367{
368 int type = get8 ();
369
370 *found = type;
371
372 SV *res;
373
374 switch (type)
251 } 375 {
376 case ASN_OBJECT_IDENTIFIER:
377 res = process_object_identifier_sv ();
378 break;
379
380 case ASN_INTEGER32:
381 res = process_integer32_sv ();
382 break;
383
384 case ASN_UNSIGNED32:
385 case ASN_COUNTER32:
386 case ASN_TIMETICKS:
387 res = process_unsigned32_sv ();
388 break;
389
390 case ASN_SEQUENCE:
391 res = newSVuv (process_length ());
392 break;
393
394 case ASN_OCTET_STRING:
395 case ASN_OPAQUE:
396 res = process_octet_string_sv ();
397 break;
398
399 default:
400 {
401 if (type > AvFILLp (av_type) || SvTYPE (AvARRAY (av_type)[type]) != SVt_PVCV)
402 {
403 error ("Unknown ASN.1 type");
404 return &PL_sv_undef;
405 }
406
407 dSP;
408 PUSHMARK (SP);
409 EXTEND (SP, 2);
410 PUSHs (msg);
411 PUSHs (sv_2mortal (newSViv (type)));
412 PUTBACK;
413 int count = call_sv (AvARRAY (av_type)[type], G_SCALAR);
414 SPAGAIN;
415 res = count ? SvREFCNT_inc (TOPs) : &PL_sv_undef;
416 }
417 }
418
419 return errflag ? &PL_sv_undef : res;
420}
421
422/////////////////////////////////////////////////////////////////////////////
423
424#if HAVE_VERSIONSORT
425
426static int
427oid_lex_cmp (const void *a_, const void *b_)
428{
429 const char *a = SvPVX (*(SV **)a_);
430 const char *b = SvPVX (*(SV **)b_);
431
432 a += *a == '.';
433 b += *b == '.';
434
435 return strverscmp (a, b);
436}
437
252#endif 438#endif
253
254 return newSVpvn (oid, app - oid);
255}
256
257static AV *av_type;
258 439
259MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS 440MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS
260 441
261PROTOTYPES: ENABLE 442PROTOTYPES: ENABLE
262 443
266void 447void
267set_type (int type, SV *cv) 448set_type (int type, SV *cv)
268 CODE: 449 CODE:
269 av_store (av_type, type, SvREFCNT_inc (x_get_cv (cv))); 450 av_store (av_type, type, SvREFCNT_inc (x_get_cv (cv)));
270 451
452void xxx(...)
453 CODE:
454 clear_bufobj ();
455
456MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message
457
271void 458void
272set_msg (SV *msg_, SV *buf_) 459_buffer_append (BUFOBJ self, SV *value)
460 ALIAS:
461 _buffer_put = 1
273 CODE: 462 PPCODE:
274 errflag = 0; 463{
275 leading_dot = -1; 464 STRLEN vlen;
276 msg = SvREFCNT_inc (msg_); 465 const char *vstr = SvPVbyte (value, vlen);
466
467 if (ix)
468 sv_insert (bufsv, 0, 0, vstr, vlen);
469 else
470 sv_catpvn (bufsv, vstr, vlen);
471
277 buf = SvPVbyte (buf_, len); 472 buf = SvPVbyte (bufsv, len);
278 cur = buf; 473 cur = buf;
279 rem = len; 474 rem = len;
280#ifdef BENCHMARK 475
281 t1 = tstamp (); 476 SV *len_sv = *hv_fetch ((HV *)cur_bufobj, "_length", sizeof ("_length") - 1, 1);
282#endif 477 sv_setiv (len_sv, len);
478
479 // some callers test for defined'ness of the returnvalue. *sigh*
480 XPUSHs (&PL_sv_yes);
481}
283 482
284void 483void
285clr_msg ()
286 CODE:
287 SvREFCNT_dec (msg);
288 buf = cur = "";
289 len = rem = 0;
290#ifdef BENCHMARK
291 printf ("%f\n", tstamp () - t1);//D
292#endif
293
294MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message
295
296void
297_buffer_get (SV *self, int count = -1) 484_buffer_get (BUFOBJ self, int count = -1)
298 PPCODE: 485 PPCODE:
299{ 486{
300 // grrr. 487 // grrr.
301 if (count < 0) 488 if (count < 0)
302 { 489 {
303 hv_delete ((HV *)SvRV (self), "_index" , 6, G_DISCARD); 490 hv_delete ((HV *)SvRV (self), "_index" , 6, G_DISCARD);
304 hv_delete ((HV *)SvRV (self), "_length", 7, G_DISCARD); 491 hv_delete ((HV *)SvRV (self), "_length", 7, G_DISCARD);
305 SV **svp = hv_fetch ((HV *)SvRV (self), "_buffer", 7, 1);
306 XPUSHs (sv_2mortal (newSVsv (*svp))); 492 XPUSHs (sv_2mortal (newSVsv (bufsv)));
307 sv_setpvn (*svp, "", 0); 493 sv_setpvn (bufsv, "", 0);
494
495 buf = "";
496 cur = buf;
497 rem = 0;
498
308 XSRETURN (1); 499 XSRETURN (1);
309 } 500 }
310 501
311 char *data = getn (count, 0); 502 char *data = getn (count, 0);
312 503
313 if (data) 504 if (data)
314 XPUSHs (sv_2mortal (newSVpvn (data, count))); 505 XPUSHs (sv_2mortal (newSVpvn (data, count)));
315} 506}
316 507
317U32 508U32
318index (SV *self, int ndx = -1) 509index (BUFOBJ self, int ndx = -1)
319 CODE: 510 CODE:
320{ 511{
321 if (ndx >= 0 && ndx < len) 512 if (ndx >= 0 && ndx < len)
322 { 513 {
323 cur = buf + ndx; 514 cur = buf + ndx;
328} 519}
329 OUTPUT: 520 OUTPUT:
330 RETVAL 521 RETVAL
331 522
332U32 523U32
333_process_length (SV *self, ...) 524_process_length (BUFOBJ self, ...)
334 ALIAS: 525 ALIAS:
335 _process_sequence = 0 526 _process_sequence = 0
336 CODE: 527 CODE:
337 RETVAL = process_length (); 528 RETVAL = process_length ();
338 OUTPUT: 529 OUTPUT:
339 RETVAL 530 RETVAL
340 531
341SV * 532SV *
342_process_integer32 (SV *self, ...) 533_process_integer32 (BUFOBJ self, ...)
343 CODE: 534 CODE:
344 RETVAL = process_integer32_sv (); 535 RETVAL = process_integer32_sv ();
345 OUTPUT: 536 OUTPUT:
346 RETVAL 537 RETVAL
347 538
348SV * 539SV *
349_process_counter (SV *self, ...) 540_process_counter (BUFOBJ self, ...)
350 ALIAS: 541 ALIAS:
351 _process_gauge = 0 542 _process_gauge = 0
352 _process_timeticks = 0 543 _process_timeticks = 0
353 CODE: 544 CODE:
354 RETVAL = process_unsigned32_sv (); 545 RETVAL = process_unsigned32_sv ();
355 OUTPUT: 546 OUTPUT:
356 RETVAL 547 RETVAL
357 548
549#if IVSIZE >= 8
550
358SV * 551SV *
552_process_counter64 (BUFOBJ self, ...)
553 CODE:
554 RETVAL = process_unsigned64_sv ();
555 OUTPUT:
556 RETVAL
557
558#endif
559
560SV *
359_process_object_identifier (SV *self, ...) 561_process_object_identifier (BUFOBJ self, ...)
360 CODE: 562 CODE:
361 RETVAL = process_object_identifier_sv (); 563 RETVAL = process_object_identifier_sv ();
362 OUTPUT: 564 OUTPUT:
363 RETVAL 565 RETVAL
364 566
365SV * 567SV *
366_process_octet_string (SV *self, ...) 568_process_octet_string (BUFOBJ self, ...)
367 ALIAS: 569 ALIAS:
368 _process_opaque = 0 570 _process_opaque = 0
369 CODE: 571 CODE:
370 RETVAL = process_octet_string_sv (); 572 RETVAL = process_octet_string_sv ();
371 OUTPUT: 573 OUTPUT:
372 RETVAL 574 RETVAL
373 575
374SV * 576SV *
375_process_ipaddress (SV *self, ...) 577_process_ipaddress (BUFOBJ self, ...)
376 CODE: 578 CODE:
377{ 579{
378 U32 length = process_length (); 580 U32 length = process_length ();
379 if (length != 4) 581 if (length != 4)
380 { 582 {
387} 589}
388 OUTPUT: 590 OUTPUT:
389 RETVAL 591 RETVAL
390 592
391SV * 593SV *
392process (SV *self, SV *expected = 0, SV *found = 0) 594process (BUFOBJ self, SV *expected = &PL_sv_undef, SV *found = 0)
393 PPCODE: 595 CODE:
394{ 596{
395 U8 type = get8 (); 597 int type;
396 598
397 if (expected && SvOK (expected) && type != SvIV (expected)) 599 RETVAL = process_sv (&type);
398 {
399 error ("Expected a different type than found");
400 XSRETURN_UNDEF;
401 }
402
403 if (type > AvFILLp (av_type) || !SvTYPE (AvARRAY (av_type)[type]) == SVt_PVCV)
404 {
405 sv_dump (AvARRAY (av_type)[type]);//D
406 error ("Unknown ASN.1 type");
407 XSRETURN_UNDEF;
408 }
409 600
410 if (found) 601 if (found)
411 sv_setiv (found, type); 602 sv_setiv (found, type);
412 603
413 //TODO: switch based on type, to avoid calling overhead 604 if (SvOK (expected) && type != SvIV (expected))
414 SV *res; 605 error ("Expected a different type than found");
606}
607 OUTPUT:
608 RETVAL
415 609
416 switch (type) 610MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::PDU
611
612SV *
613_process_var_bind_list (BUFOBJ self)
614 CODE:
615{
616 if (get8 () != ASN_SEQUENCE)
617 error ("SEQUENCE expected at beginning of VarBindList");
618 int seqlen = process_length ();
619 U8 *end = cur + seqlen;
620
621 HV *list = newHV ();
622 AV *names = newAV ();
623 HV *types = newHV ();
624
625 hv_store ((HV *)cur_bufobj, "_var_bind_list" , sizeof ("_var_bind_list" ) - 1, newRV_noinc ((SV *)list ), 0);
626 hv_store ((HV *)cur_bufobj, "_var_bind_names", sizeof ("_var_bind_names") - 1, newRV_noinc ((SV *)names), 0);
627 hv_store ((HV *)cur_bufobj, "_var_bind_types", sizeof ("_var_bind_types") - 1, newRV_noinc ((SV *)types), 0);
628
629 while (cur < end && !errflag)
417 { 630 {
631 // SEQUENCE ObjectName ObjectSyntax
632 if (get8 () != ASN_SEQUENCE)
633 error ("SEQUENCE expected at beginning of VarBind");
634 process_length ();
635
418 case ASN_OBJECT_IDENTIFIER: 636 if (get8 () != ASN_OBJECT_IDENTIFIER)
637 error ("OBJECT IDENTIFIER expected at beginning of VarBind");
638 int type, oidlen;
419 res = sv_2mortal (process_object_identifier_sv ()); 639 SV *oid = process_object_identifier_sv ();
420 break; 640 SV *val = process_sv (&type);
421 641
422 case ASN_INTEGER32: 642 hv_store_ent (types, oid, newSViv (type), 0);
423 res = sv_2mortal (process_integer32_sv ()); 643 hv_store_ent (list , oid, val, 0);
424 break; 644 av_push (names, oid);
425
426 case ASN_UNSIGNED32:
427 case ASN_COUNTER32:
428 case ASN_TIMETICKS:
429 res = sv_2mortal (process_unsigned32_sv ());
430 break;
431
432 case ASN_SEQUENCE:
433 res = sv_2mortal (newSVuv (process_length ()));
434 break;
435
436 case ASN_OCTET_STRING:
437 case ASN_OPAQUE:
438 res = sv_2mortal (process_octet_string_sv ());
439 break;
440
441 default:
442 {
443 dSP;
444 PUSHMARK (SP);
445 EXTEND (SP, 2);
446 PUSHs (self);
447 PUSHs (expected);
448 PUTBACK;
449 int count = call_sv (AvARRAY (av_type)[type], G_SCALAR);
450 SPAGAIN;
451 res = count ? TOPs : &PL_sv_undef;
452 }
453 } 645 }
646
647 // sigh - great design to do it here
648 SV *pdu_type = *hv_fetch ((HV *)cur_bufobj, "_pdu_type" , sizeof ("_pdu_type" ) - 1, 1);
454 649
455 XPUSHs (errflag ? &PL_sv_undef : res); 650 if (SvIV (pdu_type) == 0xa8) // REPORT
651 {
652 PUSHMARK (SP);
653 XPUSHs (msg);
654 PUTBACK;
655 call_method ("_report_pdu_error", G_VOID | G_DISCARD);
656 SPAGAIN;
657 XSRETURN_EMPTY;
658 }
659
660 RETVAL = newRV_inc ((SV *)list);
456} 661}
662 OUTPUT:
663 RETVAL
457 664
458#if 0
459
460MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::PDU 665MODULE = Net::SNMP::XS PACKAGE = Net::SNMP
461 666
462SV * 667void
463_process_var_bind_list (SV *self) 668oid_base_match (SV *base_, SV *oid_)
669 PROTOTYPE: $$
670 ALIAS:
671 oid_context_match = 0
672 PPCODE:
673{
674 if (!SvOK (base_) || !SvOK (oid_))
675 XSRETURN_NO;
676
677 STRLEN blen, olen;
678 char *base = SvPVbyte (base_, blen);
679 char *oid = SvPVbyte (oid_ , olen);
680
681 blen -= *base == '.'; base += *base == '.';
682 olen -= *base == '.'; oid += *oid == '.';
683
684 if (olen < blen)
685 XSRETURN_NO;
686
687 if (memcmp (base, oid, blen))
688 XSRETURN_NO;
689
690 if (oid [blen] && oid [blen] != '.')
691 XSRETURN_NO;
692
693 XSRETURN_YES;
694}
695
696#if HAVE_VERSIONSORT
697
698void
699oid_lex_sort (...)
700 PROTOTYPE: @
701 PPCODE:
702{
703 // make sure SvPVX is valid
704 int i;
705 for (i = items; i--; )
706 {
707 SV *sv = ST (i);
708
709 if (SvTYPE (sv) < SVt_PV || SvTYPE (sv) == SVt_PVAV && SvTYPE (sv) == SVt_PVHV)
710 SvPV_force_nolen (sv);
711 }
712
713 qsort (&ST (0), items, sizeof (SV *), oid_lex_cmp);
714
715 EXTEND (SP, items);
716 // we cheat somewhat by not returning copies here
717 for (i = 0; i < items; ++i)
718 PUSHs (sv_2mortal (SvREFCNT_inc (ST (i))));
719}
720
721int
722_index_cmp (const char *a, const char *b)
723 PROTOTYPE: $$
464 CODE: 724 CODE:
465{ 725 RETVAL = strverscmp (a, b);
466 # VarBindList::=SEQUENCE 726 OUTPUT:
467 if (!defined($value = $this->process(SEQUENCE))) { 727 RETVAL
468 return $this->_error;
469 }
470
471 # Using the length of the VarBindList SEQUENCE,
472 # calculate the end index.
473
474 my $end = $this->index + $value;
475
476 $this->{_var_bind_list} = {};
477 $this->{_var_bind_names} = [];
478 $this->{_var_bind_types} = {};
479
480 my ($oid, $type);
481
482 while ($this->index < $end) {
483
484 # VarBind::=SEQUENCE
485 if (!defined($this->process(SEQUENCE))) {
486 return $this->_error;
487 }
488 # name::=ObjectName
489 if (!defined($oid = $this->process(OBJECT_IDENTIFIER))) {
490 return $this->_error;
491 }
492 # value::=ObjectSyntax
493 if (!defined($value = $this->process(undef, $type))) {
494 return $this->_error;
495 }
496
497 # Create a hash consisting of the OBJECT IDENTIFIER as a
498 # key and the ObjectSyntax as the value. If there is a
499 # duplicate OBJECT IDENTIFIER in the VarBindList, we pad
500 # that OBJECT IDENTIFIER with spaces to make a unique
501 # key in the hash.
502
503 while (exists($this->{_var_bind_list}->{$oid})) {
504 $oid .= ' '; # Pad with spaces
505 }
506
507 DEBUG_INFO('{ %s => %s: %s }', $oid, asn1_itoa($type), $value);
508 $this->{_var_bind_list}->{$oid} = $value;
509 $this->{_var_bind_types}->{$oid} = $type;
510
511 # Create an array with the ObjectName OBJECT IDENTIFIERs
512 # so that the order in which the VarBinds where encoded
513 # in the PDU can be retrieved later.
514
515 push(@{$this->{_var_bind_names}}, $oid);
516
517 }
518
519 # Return an error based on the contents of the VarBindList
520 # if we received a Report-PDU.
521
522 return $this->_report_pdu_error if ($this->{_pdu_type} == REPORT);
523
524 # Return the var_bind_list hash
525 $this->{_var_bind_list};
526}
527 728
528#endif 729#endif
529 730

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines