… | |
… | |
19 | #define ASN_OPAQUE 0x44 |
19 | #define ASN_OPAQUE 0x44 |
20 | #define ASN_COUNTER64 0x46 |
20 | #define ASN_COUNTER64 0x46 |
21 | |
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 | |
|
|
26 | static SV *cur_bufobj; |
24 | static SV *msg; |
27 | static SV *msg; |
25 | static int errflag, leading_dot; |
28 | static int errflag, leading_dot; |
26 | static U8 *buf, *cur; |
29 | static U8 *buf, *cur; |
27 | static STRLEN len, rem; |
30 | static STRLEN len, rem; |
28 | |
31 | |
|
|
32 | typedef 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 | |
|
|
41 | void |
|
|
42 | clr_msg () |
|
|
43 | CODE: |
|
|
44 | SvREFCNT_dec (msg); msg = 0; |
|
|
45 | buf = cur = (U8 *)""; |
|
|
46 | len = rem = 0; |
|
|
47 | #endif |
|
|
48 | |
|
|
49 | static void |
|
|
50 | switch_bufobj (BUFOBJ neu) |
|
|
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 | |
|
|
59 | SvREFCNT_dec (msg); |
|
|
60 | msg = newSVsv (neu); |
|
|
61 | cur_bufobj = SvRV (msg); |
|
|
62 | sv_rvweaken (msg); |
|
|
63 | |
|
|
64 | SV *bufsv = *hv_fetch ((HV *)cur_bufobj, "_buffer", sizeof ("_buffer") - 1, 1); |
|
|
65 | IV index = SvIV (*hv_fetch ((HV *)cur_bufobj, "_index" , sizeof ("_index" ) - 1, 1)); |
|
|
66 | |
|
|
67 | errflag = 0; |
|
|
68 | leading_dot = -1; |
|
|
69 | buf = SvPVbyte (bufsv, len); |
|
|
70 | cur = buf + index; |
|
|
71 | rem = len - index; |
|
|
72 | } |
|
|
73 | |
|
|
74 | ///////////////////////////////////////////////////////////////////////////// |
|
|
75 | |
29 | static SV * |
76 | static SV * |
30 | x_get_cv (SV *cb_sv) |
77 | x_get_cv (SV *cb_sv) |
31 | { |
78 | { |
32 | HV *st; |
79 | HV *st; |
33 | GV *gvp; |
80 | GV *gvp; |
… | |
… | |
41 | |
88 | |
42 | static void |
89 | static void |
43 | error (const char *errmsg) |
90 | error (const char *errmsg) |
44 | { |
91 | { |
45 | errflag = 1; |
92 | errflag = 1; |
|
|
93 | |
|
|
94 | if (!msg) |
|
|
95 | croak ("Net::SNMP::XS fatal error, parser called without parsing context"); |
46 | |
96 | |
47 | dSP; |
97 | dSP; |
48 | PUSHMARK (SP); |
98 | PUSHMARK (SP); |
49 | EXTEND (SP, 2); |
99 | EXTEND (SP, 2); |
50 | PUSHs (msg); |
100 | PUSHs (msg); |
… | |
… | |
278 | U8 *end = cur + length; |
328 | U8 *end = cur + length; |
279 | U32 w = getb (); |
329 | U32 w = getb (); |
280 | |
330 | |
281 | static char oid[MAX_OID_STRLEN]; // must be static |
331 | static char oid[MAX_OID_STRLEN]; // must be static |
282 | char *app = oid; |
332 | char *app = oid; |
|
|
333 | |
|
|
334 | if (leading_dot < 0) |
|
|
335 | leading_dot = SvTRUE (*hv_fetch ((HV *)SvRV (msg), "_leading_dot", sizeof ("_leading_dot") - 1, 1)); |
283 | |
336 | |
284 | *app = '.'; app += ! ! leading_dot; |
337 | *app = '.'; app += ! ! leading_dot; |
285 | app = write_uv (app, (U8)w / 40); |
338 | app = write_uv (app, (U8)w / 40); |
286 | *app++ = '.'; |
339 | *app++ = '.'; |
287 | app = write_uv (app, (U8)w % 40); |
340 | app = write_uv (app, (U8)w % 40); |
… | |
… | |
354 | } |
407 | } |
355 | |
408 | |
356 | return errflag ? &PL_sv_undef : res; |
409 | return errflag ? &PL_sv_undef : res; |
357 | } |
410 | } |
358 | |
411 | |
|
|
412 | ///////////////////////////////////////////////////////////////////////////// |
|
|
413 | |
|
|
414 | #if HAVE_VERSIONSORT |
|
|
415 | |
|
|
416 | static int |
|
|
417 | oid_lex_cmp (const void *a_, const void *b_) |
|
|
418 | { |
|
|
419 | const char *a = SvPVX (*(SV **)a_); |
|
|
420 | const char *b = SvPVX (*(SV **)b_); |
|
|
421 | |
|
|
422 | a += *a == '.'; |
|
|
423 | b += *b == '.'; |
|
|
424 | |
|
|
425 | return strverscmp (a, b); |
|
|
426 | } |
|
|
427 | |
|
|
428 | #endif |
|
|
429 | |
359 | MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS |
430 | MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS |
360 | |
431 | |
361 | PROTOTYPES: ENABLE |
432 | PROTOTYPES: ENABLE |
362 | |
433 | |
363 | BOOT: |
434 | BOOT: |
… | |
… | |
369 | av_store (av_type, type, SvREFCNT_inc (x_get_cv (cv))); |
440 | av_store (av_type, type, SvREFCNT_inc (x_get_cv (cv))); |
370 | |
441 | |
371 | void |
442 | void |
372 | set_msg (SV *msg_, SV *buf_) |
443 | set_msg (SV *msg_, SV *buf_) |
373 | CODE: |
444 | CODE: |
374 | { |
|
|
375 | if (msg) |
|
|
376 | croak ("recursive invocation of Net::SNMP::XS parser is not supported"); |
|
|
377 | |
|
|
378 | errflag = 0; |
|
|
379 | leading_dot = -1; |
|
|
380 | msg = SvREFCNT_inc (msg_); |
|
|
381 | buf = SvPVbyte (buf_, len); |
|
|
382 | cur = buf; |
|
|
383 | rem = len; |
|
|
384 | #ifdef BENCHMARK |
|
|
385 | t1 = tstamp (); |
|
|
386 | #endif |
|
|
387 | } |
|
|
388 | |
445 | |
389 | void |
446 | void |
390 | clr_msg () |
447 | clr_msg () |
391 | CODE: |
448 | CODE: |
392 | SvREFCNT_dec (msg); msg = 0; |
|
|
393 | buf = cur = (U8 *)""; |
|
|
394 | len = rem = 0; |
|
|
395 | #ifdef BENCHMARK |
|
|
396 | printf ("%f\n", tstamp () - t1);//D |
|
|
397 | #endif |
|
|
398 | |
449 | |
399 | MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message |
450 | MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message |
400 | |
451 | |
401 | void |
452 | void |
402 | _buffer_get (SV *self, int count = -1) |
453 | _buffer_get (BUFOBJ self, int count = -1) |
403 | PPCODE: |
454 | PPCODE: |
404 | { |
455 | { |
405 | // grrr. |
456 | // grrr. |
406 | if (count < 0) |
457 | if (count < 0) |
407 | { |
458 | { |
… | |
… | |
418 | if (data) |
469 | if (data) |
419 | XPUSHs (sv_2mortal (newSVpvn (data, count))); |
470 | XPUSHs (sv_2mortal (newSVpvn (data, count))); |
420 | } |
471 | } |
421 | |
472 | |
422 | U32 |
473 | U32 |
423 | index (SV *self, int ndx = -1) |
474 | index (BUFOBJ self, int ndx = -1) |
424 | CODE: |
475 | CODE: |
425 | { |
476 | { |
426 | if (ndx >= 0 && ndx < len) |
477 | if (ndx >= 0 && ndx < len) |
427 | { |
478 | { |
428 | cur = buf + ndx; |
479 | cur = buf + ndx; |
… | |
… | |
433 | } |
484 | } |
434 | OUTPUT: |
485 | OUTPUT: |
435 | RETVAL |
486 | RETVAL |
436 | |
487 | |
437 | U32 |
488 | U32 |
438 | _process_length (SV *self, ...) |
489 | _process_length (BUFOBJ self, ...) |
439 | ALIAS: |
490 | ALIAS: |
440 | _process_sequence = 0 |
491 | _process_sequence = 0 |
441 | CODE: |
492 | CODE: |
442 | RETVAL = process_length (); |
493 | RETVAL = process_length (); |
443 | OUTPUT: |
494 | OUTPUT: |
444 | RETVAL |
495 | RETVAL |
445 | |
496 | |
446 | SV * |
497 | SV * |
447 | _process_integer32 (SV *self, ...) |
498 | _process_integer32 (BUFOBJ self, ...) |
448 | CODE: |
499 | CODE: |
449 | RETVAL = process_integer32_sv (); |
500 | RETVAL = process_integer32_sv (); |
450 | OUTPUT: |
501 | OUTPUT: |
451 | RETVAL |
502 | RETVAL |
452 | |
503 | |
453 | SV * |
504 | SV * |
454 | _process_counter (SV *self, ...) |
505 | _process_counter (BUFOBJ self, ...) |
455 | ALIAS: |
506 | ALIAS: |
456 | _process_gauge = 0 |
507 | _process_gauge = 0 |
457 | _process_timeticks = 0 |
508 | _process_timeticks = 0 |
458 | CODE: |
509 | CODE: |
459 | RETVAL = process_unsigned32_sv (); |
510 | RETVAL = process_unsigned32_sv (); |
… | |
… | |
461 | RETVAL |
512 | RETVAL |
462 | |
513 | |
463 | #if IVSIZE >= 8 |
514 | #if IVSIZE >= 8 |
464 | |
515 | |
465 | SV * |
516 | SV * |
466 | _process_counter64 (SV *self, ...) |
517 | _process_counter64 (BUFOBJ self, ...) |
467 | CODE: |
518 | CODE: |
468 | RETVAL = process_unsigned64_sv (); |
519 | RETVAL = process_unsigned64_sv (); |
469 | OUTPUT: |
520 | OUTPUT: |
470 | RETVAL |
521 | RETVAL |
471 | |
522 | |
472 | #endif |
523 | #endif |
473 | |
524 | |
474 | SV * |
525 | SV * |
475 | _process_object_identifier (SV *self, ...) |
526 | _process_object_identifier (BUFOBJ self, ...) |
476 | CODE: |
527 | CODE: |
477 | RETVAL = process_object_identifier_sv (); |
528 | RETVAL = process_object_identifier_sv (); |
478 | OUTPUT: |
529 | OUTPUT: |
479 | RETVAL |
530 | RETVAL |
480 | |
531 | |
481 | SV * |
532 | SV * |
482 | _process_octet_string (SV *self, ...) |
533 | _process_octet_string (BUFOBJ self, ...) |
483 | ALIAS: |
534 | ALIAS: |
484 | _process_opaque = 0 |
535 | _process_opaque = 0 |
485 | CODE: |
536 | CODE: |
486 | RETVAL = process_octet_string_sv (); |
537 | RETVAL = process_octet_string_sv (); |
487 | OUTPUT: |
538 | OUTPUT: |
488 | RETVAL |
539 | RETVAL |
489 | |
540 | |
490 | SV * |
541 | SV * |
491 | _process_ipaddress (SV *self, ...) |
542 | _process_ipaddress (BUFOBJ self, ...) |
492 | CODE: |
543 | CODE: |
493 | { |
544 | { |
494 | U32 length = process_length (); |
545 | U32 length = process_length (); |
495 | if (length != 4) |
546 | if (length != 4) |
496 | { |
547 | { |
… | |
… | |
503 | } |
554 | } |
504 | OUTPUT: |
555 | OUTPUT: |
505 | RETVAL |
556 | RETVAL |
506 | |
557 | |
507 | SV * |
558 | SV * |
508 | process (SV *self, SV *expected = &PL_sv_undef, SV *found = 0) |
559 | process (BUFOBJ self, SV *expected = &PL_sv_undef, SV *found = 0) |
509 | CODE: |
560 | CODE: |
510 | { |
561 | { |
511 | int type; |
562 | int type; |
512 | |
563 | |
513 | RETVAL = process_sv (&type); |
564 | RETVAL = process_sv (&type); |
… | |
… | |
522 | RETVAL |
573 | RETVAL |
523 | |
574 | |
524 | MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::PDU |
575 | MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::PDU |
525 | |
576 | |
526 | SV * |
577 | SV * |
527 | _process_var_bind_list (SV *self) |
578 | _process_var_bind_list (BUFOBJ self) |
528 | CODE: |
579 | CODE: |
529 | { |
580 | { |
530 | if (get8 () != ASN_SEQUENCE) |
581 | if (get8 () != ASN_SEQUENCE) |
531 | error ("SEQUENCE expected at beginning of VarBindList"); |
582 | error ("SEQUENCE expected at beginning of VarBindList"); |
532 | int seqlen = process_length (); |
583 | int seqlen = process_length (); |
… | |
… | |
534 | |
585 | |
535 | HV *list = newHV (); |
586 | HV *list = newHV (); |
536 | AV *names = newAV (); |
587 | AV *names = newAV (); |
537 | HV *types = newHV (); |
588 | HV *types = newHV (); |
538 | |
589 | |
539 | hv_store ((HV *)SvRV (self), "_var_bind_list" , sizeof ("_var_bind_list" ) - 1, newRV_noinc ((SV *)list ), 0); |
590 | hv_store ((HV *)cur_bufobj, "_var_bind_list" , sizeof ("_var_bind_list" ) - 1, newRV_noinc ((SV *)list ), 0); |
540 | hv_store ((HV *)SvRV (self), "_var_bind_names", sizeof ("_var_bind_names") - 1, newRV_noinc ((SV *)names), 0); |
591 | hv_store ((HV *)cur_bufobj, "_var_bind_names", sizeof ("_var_bind_names") - 1, newRV_noinc ((SV *)names), 0); |
541 | hv_store ((HV *)SvRV (self), "_var_bind_types", sizeof ("_var_bind_types") - 1, newRV_noinc ((SV *)types), 0); |
592 | hv_store ((HV *)cur_bufobj, "_var_bind_types", sizeof ("_var_bind_types") - 1, newRV_noinc ((SV *)types), 0); |
542 | |
593 | |
543 | while (cur < end && !errflag) |
594 | while (cur < end && !errflag) |
544 | { |
595 | { |
545 | // SEQUENCE ObjectName ObjectSyntax |
596 | // SEQUENCE ObjectName ObjectSyntax |
546 | if (get8 () != ASN_SEQUENCE) |
597 | if (get8 () != ASN_SEQUENCE) |
… | |
… | |
556 | hv_store_ent (types, oid, newSViv (type), 0); |
607 | hv_store_ent (types, oid, newSViv (type), 0); |
557 | hv_store_ent (list , oid, val, 0); |
608 | hv_store_ent (list , oid, val, 0); |
558 | av_push (names, oid); |
609 | av_push (names, oid); |
559 | } |
610 | } |
560 | |
611 | |
561 | //return $this->_report_pdu_error if ($this->{_pdu_type} == REPORT); |
612 | // sigh - great design to do it here |
|
|
613 | SV *pdu_type = *hv_fetch ((HV *)cur_bufobj, "_pdu_type" , sizeof ("_pdu_type" ) - 1, 1); |
|
|
614 | |
|
|
615 | if (SvIV (pdu_type) == 0xa8) // REPORT |
|
|
616 | { |
|
|
617 | PUSHMARK (SP); |
|
|
618 | XPUSHs (msg); |
|
|
619 | PUTBACK; |
|
|
620 | call_method ("_report_pdu_error", G_VOID | G_DISCARD); |
|
|
621 | SPAGAIN; |
|
|
622 | XSRETURN_EMPTY; |
|
|
623 | } |
562 | |
624 | |
563 | RETVAL = newRV_inc ((SV *)list); |
625 | RETVAL = newRV_inc ((SV *)list); |
564 | } |
626 | } |
565 | OUTPUT: |
627 | OUTPUT: |
566 | RETVAL |
628 | RETVAL |
567 | |
629 | |
|
|
630 | MODULE = Net::SNMP::XS PACKAGE = Net::SNMP |
568 | |
631 | |
|
|
632 | void |
|
|
633 | oid_base_match (SV *base_, SV *oid_) |
|
|
634 | PROTOTYPE: $$ |
|
|
635 | ALIAS: |
|
|
636 | oid_context_match = 0 |
|
|
637 | PPCODE: |
|
|
638 | { |
|
|
639 | if (!SvOK (base_) || !SvOK (oid_)) |
|
|
640 | XSRETURN_NO; |
|
|
641 | |
|
|
642 | STRLEN blen, olen; |
|
|
643 | char *base = SvPV (base_, blen); |
|
|
644 | char *oid = SvPV (oid_ , olen); |
|
|
645 | |
|
|
646 | blen -= *base == '.'; base += *base == '.'; |
|
|
647 | olen -= *base == '.'; oid += *oid == '.'; |
|
|
648 | |
|
|
649 | if (olen < blen) |
|
|
650 | XSRETURN_NO; |
|
|
651 | |
|
|
652 | if (memcmp (base, oid, blen)) |
|
|
653 | XSRETURN_NO; |
|
|
654 | |
|
|
655 | if (oid [blen] && oid [blen] != '.') |
|
|
656 | XSRETURN_NO; |
|
|
657 | |
|
|
658 | XSRETURN_YES; |
|
|
659 | } |
|
|
660 | |
|
|
661 | #if HAVE_VERSIONSORT |
|
|
662 | |
|
|
663 | void |
|
|
664 | oid_lex_sort (...) |
|
|
665 | PROTOTYPE: @ |
|
|
666 | PPCODE: |
|
|
667 | { |
|
|
668 | // make sure SvPVX is valid |
|
|
669 | int i; |
|
|
670 | for (i = items; i--; ) |
|
|
671 | { |
|
|
672 | SV *sv = ST (i); |
|
|
673 | |
|
|
674 | if (SvTYPE (sv) < SVt_PV || SvTYPE (sv) == SVt_PVAV && SvTYPE (sv) == SVt_PVHV) |
|
|
675 | SvPV_force_nolen (sv); |
|
|
676 | } |
|
|
677 | |
|
|
678 | qsort (&ST (0), items, sizeof (SV *), oid_lex_cmp); |
|
|
679 | |
|
|
680 | EXTEND (SP, items); |
|
|
681 | // we cheat somewhat by not returning copies here |
|
|
682 | for (i = 0; i < items; ++i) |
|
|
683 | PUSHs (sv_2mortal (SvREFCNT_inc (ST (i)))); |
|
|
684 | } |
|
|
685 | |
|
|
686 | int |
|
|
687 | _index_cmp (const char *a, const char *b) |
|
|
688 | PROTOTYPE: $$ |
|
|
689 | CODE: |
|
|
690 | RETVAL = strverscmp (a, b); |
|
|
691 | OUTPUT: |
|
|
692 | RETVAL |
|
|
693 | |
|
|
694 | #endif |
|
|
695 | |