… | |
… | |
57 | static int errflag, leading_dot; |
57 | static int errflag, leading_dot; |
58 | static U8 *buf, *cur; |
58 | static U8 *buf, *cur; |
59 | static STRLEN len, rem; |
59 | static STRLEN len, rem; |
60 | |
60 | |
61 | typedef SV *BUFOBJ; |
61 | typedef SV *BUFOBJ; |
62 | |
|
|
63 | // for "small" integers, return a readonly sv, otherwise create a new one |
|
|
64 | static SV *newSVcacheint (int val) |
|
|
65 | { |
|
|
66 | static SV *cache[32]; |
|
|
67 | |
|
|
68 | if (val < 0 || val >= sizeof (cache)) |
|
|
69 | return newSViv (val); |
|
|
70 | |
|
|
71 | if (!cache [val]) |
|
|
72 | { |
|
|
73 | cache [val] = newSVuv (val); |
|
|
74 | SvREADONLY_on (cache [val]); |
|
|
75 | } |
|
|
76 | |
|
|
77 | return SvREFCNT_inc_NN (cache [val]); |
|
|
78 | } |
|
|
79 | |
62 | |
80 | ///////////////////////////////////////////////////////////////////////////// |
63 | ///////////////////////////////////////////////////////////////////////////// |
81 | |
64 | |
82 | #if 0 |
65 | #if 0 |
83 | if (msg) |
66 | if (msg) |
… | |
… | |
465 | } |
448 | } |
466 | |
449 | |
467 | return errflag ? &PL_sv_undef : res; |
450 | return errflag ? &PL_sv_undef : res; |
468 | } |
451 | } |
469 | |
452 | |
470 | static SV * |
|
|
471 | ber_decode () |
|
|
472 | { |
|
|
473 | int identifier = get8 (); |
|
|
474 | |
|
|
475 | SV *res; |
|
|
476 | |
|
|
477 | int constructed = identifier & ASN_CONSTRUCTED; |
|
|
478 | int klass = identifier & ASN_CLASS_MASK; |
|
|
479 | int tag = identifier & ASN_TAG_MASK; |
|
|
480 | |
|
|
481 | if (tag == ASN_TAG_BER) |
|
|
482 | tag = getb (); |
|
|
483 | |
|
|
484 | #if 0 |
|
|
485 | if (/type & ASN_TAG_MASK) == ASN_TAG_MASK) |
|
|
486 | /* TODO: ber tag follows */; |
|
|
487 | #endif |
|
|
488 | |
|
|
489 | if (constructed) |
|
|
490 | { |
|
|
491 | U32 len = process_length (); |
|
|
492 | U32 seqend = (cur - buf) + len; |
|
|
493 | AV *av = (AV *)sv_2mortal ((SV *)newAV ()); |
|
|
494 | |
|
|
495 | while (cur < buf + seqend) |
|
|
496 | av_push (av, ber_decode ()); |
|
|
497 | |
|
|
498 | if (cur > buf + seqend) |
|
|
499 | croak ("constructed type %02x overflow (%x %x)\n", identifier, cur - buf, seqend); |
|
|
500 | |
|
|
501 | res = newRV_inc ((SV *)av); |
|
|
502 | } |
|
|
503 | else |
|
|
504 | switch (identifier) |
|
|
505 | { |
|
|
506 | case ASN_NULL: |
|
|
507 | res = &PL_sv_undef; |
|
|
508 | break; |
|
|
509 | |
|
|
510 | case ASN_OBJECT_IDENTIFIER: |
|
|
511 | res = process_object_identifier_sv (); |
|
|
512 | break; |
|
|
513 | |
|
|
514 | case ASN_INTEGER32: |
|
|
515 | res = process_integer32_sv (); |
|
|
516 | break; |
|
|
517 | |
|
|
518 | case ASN_APPLICATION | ASN_UNSIGNED32: |
|
|
519 | case ASN_APPLICATION | ASN_COUNTER32: |
|
|
520 | case ASN_APPLICATION | ASN_TIMETICKS: |
|
|
521 | res = process_unsigned32_sv (); |
|
|
522 | break; |
|
|
523 | |
|
|
524 | #if 0 // handled by default case |
|
|
525 | case ASN_OCTET_STRING: |
|
|
526 | case ASN_APPLICATION | ASN_IPADDRESS: |
|
|
527 | case ASN_APPLICATION | ASN_OPAQUE: |
|
|
528 | res = process_octet_string_sv (); |
|
|
529 | break; |
|
|
530 | #endif |
|
|
531 | |
|
|
532 | case ASN_APPLICATION | ASN_COUNTER64: |
|
|
533 | res = process_integer64_sv (); |
|
|
534 | break; |
|
|
535 | |
|
|
536 | default: |
|
|
537 | res = process_octet_string_sv (); |
|
|
538 | break; |
|
|
539 | } |
|
|
540 | |
|
|
541 | if (errflag) |
|
|
542 | croak ("some error"); |
|
|
543 | |
|
|
544 | AV *av = newAV (); |
|
|
545 | av_fill (av, BER_ARRAYSIZE - 1); |
|
|
546 | AvARRAY (av)[BER_CLASS ] = newSVcacheint (klass >> ASN_CLASS_SHIFT); |
|
|
547 | AvARRAY (av)[BER_TAG ] = newSVcacheint (tag); |
|
|
548 | AvARRAY (av)[BER_CONSTRUCTED] = newSVcacheint (constructed ? 1 : 0); |
|
|
549 | AvARRAY (av)[BER_DATA ] = res; |
|
|
550 | res = newRV_noinc ((SV *)av); |
|
|
551 | |
|
|
552 | return errflag ? &PL_sv_undef : res; |
|
|
553 | } |
|
|
554 | |
|
|
555 | ///////////////////////////////////////////////////////////////////////////// |
453 | ///////////////////////////////////////////////////////////////////////////// |
556 | |
454 | |
557 | #if HAVE_VERSIONSORT |
455 | #if HAVE_VERSIONSORT |
558 | |
456 | |
559 | static int |
457 | static int |
… | |
… | |
573 | MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS |
471 | MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS |
574 | |
472 | |
575 | PROTOTYPES: ENABLE |
473 | PROTOTYPES: ENABLE |
576 | |
474 | |
577 | BOOT: |
475 | BOOT: |
578 | { |
|
|
579 | HV *stash = gv_stashpv ("Net::SNMP::XS", 1); |
|
|
580 | |
|
|
581 | static const struct { |
|
|
582 | const char *name; |
|
|
583 | IV iv; |
|
|
584 | } *civ, const_iv[] = { |
|
|
585 | { "ASN_BOOLEAN", ASN_BOOLEAN }, |
|
|
586 | { "ASN_INTEGER32", ASN_INTEGER32 }, |
|
|
587 | { "ASN_BIT_STRING", ASN_BIT_STRING }, |
|
|
588 | { "ASN_OCTET_STRING", ASN_OCTET_STRING }, |
|
|
589 | { "ASN_NULL", ASN_NULL }, |
|
|
590 | { "ASN_OBJECT_IDENTIFIER", ASN_OBJECT_IDENTIFIER }, |
|
|
591 | { "ASN_TAG_BER", ASN_TAG_BER }, |
|
|
592 | { "ASN_TAG_MASK", ASN_TAG_MASK }, |
|
|
593 | { "ASN_CONSTRUCTED", ASN_CONSTRUCTED }, |
|
|
594 | { "ASN_UNIVERSAL", ASN_UNIVERSAL >> ASN_CLASS_SHIFT }, |
|
|
595 | { "ASN_APPLICATION", ASN_APPLICATION >> ASN_CLASS_SHIFT }, |
|
|
596 | { "ASN_CONTEXT", ASN_CONTEXT >> ASN_CLASS_SHIFT }, |
|
|
597 | { "ASN_PRIVATE", ASN_PRIVATE >> ASN_CLASS_SHIFT }, |
|
|
598 | { "ASN_CLASS_MASK", ASN_CLASS_MASK }, |
|
|
599 | { "ASN_CLASS_SHIFT", ASN_CLASS_SHIFT }, |
|
|
600 | { "ASN_SEQUENCE", ASN_SEQUENCE }, |
|
|
601 | { "ASN_IPADDRESS", ASN_IPADDRESS }, |
|
|
602 | { "ASN_COUNTER32", ASN_COUNTER32 }, |
|
|
603 | { "ASN_UNSIGNED32", ASN_UNSIGNED32 }, |
|
|
604 | { "ASN_TIMETICKS", ASN_TIMETICKS }, |
|
|
605 | { "ASN_OPAQUE", ASN_OPAQUE }, |
|
|
606 | { "ASN_COUNTER64", ASN_COUNTER64 }, |
|
|
607 | |
|
|
608 | { "BER_CLASS" , BER_CLASS }, |
|
|
609 | { "BER_TAG" , BER_TAG }, |
|
|
610 | { "BER_CONSTRUCTED", BER_CONSTRUCTED }, |
|
|
611 | { "BER_DATA" , BER_DATA }, |
|
|
612 | }; |
|
|
613 | |
|
|
614 | for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--) |
|
|
615 | newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv)); |
|
|
616 | |
|
|
617 | av_type = newAV (); |
476 | av_type = newAV (); |
618 | } |
|
|
619 | |
477 | |
620 | void |
478 | void |
621 | set_type (int type, SV *cv) |
479 | set_type (int type, SV *cv) |
622 | CODE: |
480 | CODE: |
623 | cv = x_get_cv (cv); |
481 | cv = x_get_cv (cv); |
624 | assert (SvTYPE (cv) == SVt_PVCV); |
482 | assert (SvTYPE (cv) == SVt_PVCV); |
625 | av_store (av_type, type, SvREFCNT_inc_NN (cv)); |
483 | av_store (av_type, type, SvREFCNT_inc_NN (cv)); |
626 | |
|
|
627 | SV * |
|
|
628 | ber_decode (SV *ber) |
|
|
629 | CODE: |
|
|
630 | { |
|
|
631 | clear_bufobj (); |
|
|
632 | |
|
|
633 | errflag = 0; |
|
|
634 | leading_dot = 0; |
|
|
635 | |
|
|
636 | bufsv = ber; |
|
|
637 | |
|
|
638 | buf = SvPVbyte (bufsv, len); |
|
|
639 | cur = buf; |
|
|
640 | rem = len; |
|
|
641 | |
|
|
642 | RETVAL = ber_decode (); |
|
|
643 | } |
|
|
644 | OUTPUT: RETVAL |
|
|
645 | |
|
|
646 | void |
|
|
647 | ber_eq (SV *tuple, SV *klass = &PL_sv_undef, SV *tag = &PL_sv_undef, SV *constructed = &PL_sv_undef, SV *data = &PL_sv_undef) |
|
|
648 | PROTOTYPE: $;$$$ |
|
|
649 | PPCODE: |
|
|
650 | { |
|
|
651 | if (!SvOK (tuple)) |
|
|
652 | XSRETURN_NO; |
|
|
653 | |
|
|
654 | if (!SvROK (tuple) || SvTYPE (SvRV (tuple)) != SVt_PVAV) |
|
|
655 | croak ("ber_seq: tuple must be ber tuple (array-ref)"); |
|
|
656 | |
|
|
657 | AV *av = (AV *)SvRV (tuple); |
|
|
658 | |
|
|
659 | XPUSHs ( |
|
|
660 | (!SvOK (klass) || SvIV (AvARRAY (av)[BER_CLASS ]) == SvIV (klass)) |
|
|
661 | && (!SvOK (tag) || SvIV (AvARRAY (av)[BER_TAG ]) == SvIV (tag)) |
|
|
662 | && (!SvOK (constructed) || !SvIV (AvARRAY (av)[BER_CONSTRUCTED]) == !SvIV (constructed)) |
|
|
663 | && (!SvOK (data) || sv_eq (AvARRAY (av)[BER_DATA ], data)) |
|
|
664 | ? &PL_sv_yes : &PL_sv_no); |
|
|
665 | } |
|
|
666 | |
|
|
667 | void |
|
|
668 | ber_seq (SV *tuple) |
|
|
669 | PROTOTYPE: $ |
|
|
670 | PPCODE: |
|
|
671 | { |
|
|
672 | if (!SvOK (tuple)) |
|
|
673 | XSRETURN_UNDEF; |
|
|
674 | |
|
|
675 | if (!SvROK (tuple) || SvTYPE (SvRV (tuple)) != SVt_PVAV) |
|
|
676 | croak ("ber_seq: tuple must be ber tuple (array-ref)"); |
|
|
677 | |
|
|
678 | AV *av = (AV *)SvRV (tuple); |
|
|
679 | |
|
|
680 | XPUSHs ( |
|
|
681 | SvIV (AvARRAY (av)[BER_CLASS ]) == ASN_UNIVERSAL |
|
|
682 | && SvIV (AvARRAY (av)[BER_TAG ]) == ASN_SEQUENCE |
|
|
683 | && SvIV (AvARRAY (av)[BER_CONSTRUCTED]) |
|
|
684 | ? AvARRAY (av)[BER_DATA] : &PL_sv_undef); |
|
|
685 | } |
|
|
686 | |
|
|
687 | void |
|
|
688 | ber_i32 (SV *tuple, IV value) |
|
|
689 | PROTOTYPE: $$ |
|
|
690 | PPCODE: |
|
|
691 | { |
|
|
692 | if (!SvOK (tuple)) |
|
|
693 | XSRETURN_NO; |
|
|
694 | |
|
|
695 | if (!SvROK (tuple) || SvTYPE (SvRV (tuple)) != SVt_PVAV) |
|
|
696 | croak ("ber_seq: tuple must be ber tuple (array-ref)"); |
|
|
697 | |
|
|
698 | AV *av = (AV *)SvRV (tuple); |
|
|
699 | |
|
|
700 | XPUSHs ( |
|
|
701 | SvIV (AvARRAY (av)[BER_CLASS ]) == ASN_UNIVERSAL |
|
|
702 | && SvIV (AvARRAY (av)[BER_TAG ]) == ASN_INTEGER32 |
|
|
703 | && !SvIV (AvARRAY (av)[BER_CONSTRUCTED]) |
|
|
704 | && SvIV (AvARRAY (av)[BER_DATA ]) == value |
|
|
705 | ? &PL_sv_yes : &PL_sv_no); |
|
|
706 | } |
|
|
707 | |
|
|
708 | void |
|
|
709 | ber_oid (SV *tuple, SV *oid) |
|
|
710 | PROTOTYPE: $$ |
|
|
711 | PPCODE: |
|
|
712 | { |
|
|
713 | if (!SvOK (tuple)) |
|
|
714 | XSRETURN_NO; |
|
|
715 | |
|
|
716 | if (!SvROK (tuple) || SvTYPE (SvRV (tuple)) != SVt_PVAV) |
|
|
717 | croak ("ber_seq: tuple must be ber tuple (array-ref)"); |
|
|
718 | |
|
|
719 | AV *av = (AV *)SvRV (tuple); |
|
|
720 | |
|
|
721 | XPUSHs ( |
|
|
722 | SvIV (AvARRAY (av)[BER_CLASS ]) == ASN_UNIVERSAL |
|
|
723 | && SvIV (AvARRAY (av)[BER_TAG ]) == ASN_OBJECT_IDENTIFIER |
|
|
724 | && !SvIV (AvARRAY (av)[BER_CONSTRUCTED]) |
|
|
725 | && sv_eq (AvARRAY (av)[BER_DATA], oid) |
|
|
726 | ? &PL_sv_yes : &PL_sv_no); |
|
|
727 | } |
|
|
728 | |
484 | |
729 | MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message |
485 | MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message |
730 | |
486 | |
731 | void |
487 | void |
732 | _buffer_append (BUFOBJ self, SV *value) |
488 | _buffer_append (BUFOBJ self, SV *value) |