… | |
… | |
5 | // C99 required |
5 | // C99 required |
6 | |
6 | |
7 | //#define BENCHMARK |
7 | //#define BENCHMARK |
8 | |
8 | |
9 | enum { |
9 | enum { |
|
|
10 | // ASN_TAG |
10 | ASN_BOOLEAN = 0x01, |
11 | ASN_BOOLEAN = 0x01, |
11 | ASN_INTEGER32 = 0x02, |
12 | ASN_INTEGER32 = 0x02, |
12 | ASN_BIT_STRING = 0x03, |
13 | ASN_BIT_STRING = 0x03, |
13 | ASN_OCTET_STRING = 0x04, |
14 | ASN_OCTET_STRING = 0x04, |
14 | ASN_NULL = 0x05, |
15 | ASN_NULL = 0x05, |
15 | ASN_OBJECT_IDENTIFIER = 0x06, |
16 | ASN_OBJECT_IDENTIFIER = 0x06, |
|
|
17 | ASN_SEQUENCE = 0x10, |
16 | |
18 | |
17 | ASN_TAG_BER = 0x1f, |
19 | ASN_TAG_BER = 0x1f, |
18 | ASN_TAG_MASK = 0x1f, |
20 | ASN_TAG_MASK = 0x1f, |
19 | |
21 | |
|
|
22 | // primitive/constructed |
20 | ASN_CONSTRUCTED = 0x20, |
23 | ASN_CONSTRUCTED = 0x20, |
21 | |
24 | |
|
|
25 | // ASN_CLASS |
22 | ASN_UNIVERSAL = 0x00, |
26 | ASN_UNIVERSAL = 0x00, |
23 | ASN_APPLICATION = 0x40, |
27 | ASN_APPLICATION = 0x40, |
24 | ASN_CONTEXT = 0x80, |
28 | ASN_CONTEXT = 0x80, |
25 | ASN_PRIVATE = 0xc0, |
29 | ASN_PRIVATE = 0xc0, |
26 | |
30 | |
27 | ASN_CLASS_MASK = 0xc0, |
31 | ASN_CLASS_MASK = 0xc0, |
28 | ASN_CLASS_SHIFT = 6, |
32 | ASN_CLASS_SHIFT = 6, |
29 | |
33 | |
30 | ASN_SEQUENCE = ASN_CONSTRUCTED | 0x10, |
34 | // ASN_APPLICATION |
31 | ASN_IPADDRESS = ASN_APPLICATION | 0x00, |
35 | ASN_IPADDRESS = 0x00, |
32 | ASN_COUNTER32 = ASN_APPLICATION | 0x01, |
36 | ASN_COUNTER32 = 0x01, |
33 | ASN_UNSIGNED32 = ASN_APPLICATION | 0x02, |
37 | ASN_UNSIGNED32 = 0x02, |
34 | ASN_TIMETICKS = ASN_APPLICATION | 0x03, |
38 | ASN_TIMETICKS = 0x03, |
35 | ASN_OPAQUE = ASN_APPLICATION | 0x04, |
39 | ASN_OPAQUE = 0x04, |
36 | ASN_COUNTER64 = ASN_APPLICATION | 0x06, |
40 | ASN_COUNTER64 = 0x06, |
|
|
41 | }; |
|
|
42 | |
|
|
43 | enum { |
|
|
44 | BER_CLASS = 0, |
|
|
45 | BER_TAG = 1, |
|
|
46 | BER_CONSTRUCTED = 2, |
|
|
47 | BER_DATA = 3, |
|
|
48 | BER_ARRAYSIZE |
37 | }; |
49 | }; |
38 | |
50 | |
39 | #define MAX_OID_STRLEN 4096 |
51 | #define MAX_OID_STRLEN 4096 |
40 | |
52 | |
41 | #define HAVE_VERSIONSORT defined (_GNU_SOURCE) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1 |
53 | #define HAVE_VERSIONSORT defined (_GNU_SOURCE) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1 |
… | |
… | |
413 | |
425 | |
414 | case ASN_INTEGER32: |
426 | case ASN_INTEGER32: |
415 | res = process_integer32_sv (); |
427 | res = process_integer32_sv (); |
416 | break; |
428 | break; |
417 | |
429 | |
418 | case ASN_UNSIGNED32: |
430 | case ASN_APPLICATION | ASN_UNSIGNED32: |
419 | case ASN_COUNTER32: |
431 | case ASN_APPLICATION | ASN_COUNTER32: |
420 | case ASN_TIMETICKS: |
432 | case ASN_APPLICATION | ASN_TIMETICKS: |
421 | res = process_unsigned32_sv (); |
433 | res = process_unsigned32_sv (); |
422 | break; |
434 | break; |
423 | |
435 | |
424 | case ASN_SEQUENCE: |
436 | case ASN_SEQUENCE | ASN_CONSTRUCTED: |
425 | res = newSVuv (process_length ()); |
437 | res = newSVuv (process_length ()); |
426 | break; |
438 | break; |
427 | |
439 | |
428 | case ASN_OCTET_STRING: |
440 | case ASN_OCTET_STRING: |
429 | case ASN_OPAQUE: |
441 | case ASN_APPLICATION | ASN_OPAQUE: |
430 | res = process_octet_string_sv (); |
442 | res = process_octet_string_sv (); |
431 | break; |
443 | break; |
432 | |
444 | |
433 | default: |
445 | default: |
434 | { |
446 | { |
… | |
… | |
454 | |
466 | |
455 | return errflag ? &PL_sv_undef : res; |
467 | return errflag ? &PL_sv_undef : res; |
456 | } |
468 | } |
457 | |
469 | |
458 | static SV * |
470 | static SV * |
459 | decode_ber () |
471 | ber_decode () |
460 | { |
472 | { |
461 | int identifier = get8 (); |
473 | int identifier = get8 (); |
462 | |
474 | |
463 | SV *res; |
475 | SV *res; |
464 | |
476 | |
… | |
… | |
479 | U32 len = process_length (); |
491 | U32 len = process_length (); |
480 | U32 seqend = (cur - buf) + len; |
492 | U32 seqend = (cur - buf) + len; |
481 | AV *av = (AV *)sv_2mortal ((SV *)newAV ()); |
493 | AV *av = (AV *)sv_2mortal ((SV *)newAV ()); |
482 | |
494 | |
483 | while (cur < buf + seqend) |
495 | while (cur < buf + seqend) |
484 | { |
|
|
485 | av_push (av, decode_ber ()); |
496 | av_push (av, ber_decode ()); |
486 | } |
|
|
487 | |
497 | |
488 | if (cur > buf + seqend) |
498 | if (cur > buf + seqend) |
489 | croak ("constructed type %02x overflow (%x %x)\n", identifier, cur - buf, seqend); |
499 | croak ("constructed type %02x overflow (%x %x)\n", identifier, cur - buf, seqend); |
490 | |
500 | |
491 | res = newRV_inc ((SV *)av); |
501 | res = newRV_inc ((SV *)av); |
492 | } |
502 | } |
493 | else |
503 | else |
494 | switch (identifier) |
504 | switch (identifier) |
495 | { |
505 | { |
|
|
506 | case ASN_NULL: |
|
|
507 | res = &PL_sv_undef; |
|
|
508 | break; |
|
|
509 | |
496 | case ASN_OBJECT_IDENTIFIER: |
510 | case ASN_OBJECT_IDENTIFIER: |
497 | res = process_object_identifier_sv (); |
511 | res = process_object_identifier_sv (); |
498 | break; |
512 | break; |
499 | |
513 | |
500 | case ASN_INTEGER32: |
514 | case ASN_INTEGER32: |
501 | res = process_integer32_sv (); |
515 | res = process_integer32_sv (); |
502 | break; |
516 | break; |
503 | |
517 | |
504 | case ASN_UNSIGNED32: |
518 | case ASN_APPLICATION | ASN_UNSIGNED32: |
505 | case ASN_COUNTER32: |
519 | case ASN_APPLICATION | ASN_COUNTER32: |
506 | case ASN_TIMETICKS: |
520 | case ASN_APPLICATION | ASN_TIMETICKS: |
507 | res = process_unsigned32_sv (); |
521 | res = process_unsigned32_sv (); |
508 | break; |
522 | break; |
509 | |
523 | |
510 | #if 0 // handled by default case |
524 | #if 0 // handled by default case |
511 | case ASN_IPADDRESS: |
|
|
512 | case ASN_OCTET_STRING: |
525 | case ASN_OCTET_STRING: |
513 | case ASN_OPAQUE: |
526 | case ASN_APPLICATION | ASN_IPADDRESS: |
|
|
527 | case ASN_APPLICATION | ASN_OPAQUE: |
514 | res = process_octet_string_sv (); |
528 | res = process_octet_string_sv (); |
515 | break; |
529 | break; |
516 | #endif |
530 | #endif |
517 | |
531 | |
518 | case ASN_COUNTER64: |
532 | case ASN_APPLICATION | ASN_COUNTER64: |
519 | res = process_integer64_sv (); |
533 | res = process_integer64_sv (); |
520 | break; |
534 | break; |
521 | |
535 | |
522 | default: |
536 | default: |
523 | res = process_octet_string_sv (); |
537 | res = process_octet_string_sv (); |
… | |
… | |
526 | |
540 | |
527 | if (errflag) |
541 | if (errflag) |
528 | croak ("some error"); |
542 | croak ("some error"); |
529 | |
543 | |
530 | AV *av = newAV (); |
544 | AV *av = newAV (); |
531 | av_fill (av, 4-1); |
545 | av_fill (av, BER_ARRAYSIZE - 1); |
532 | AvARRAY (av)[0] = newSVcacheint (tag); |
|
|
533 | AvARRAY (av)[1] = newSVcacheint (klass >> ASN_CLASS_SHIFT); |
546 | AvARRAY (av)[BER_CLASS ] = newSVcacheint (klass >> ASN_CLASS_SHIFT); |
|
|
547 | AvARRAY (av)[BER_TAG ] = newSVcacheint (tag); |
534 | AvARRAY (av)[2] = newSVcacheint (constructed ? 1 : 0); |
548 | AvARRAY (av)[BER_CONSTRUCTED] = newSVcacheint (constructed ? 1 : 0); |
535 | AvARRAY (av)[3] = res; |
549 | AvARRAY (av)[BER_DATA ] = res; |
536 | res = newRV_noinc ((SV *)av); |
550 | res = newRV_noinc ((SV *)av); |
537 | |
551 | |
538 | return errflag ? &PL_sv_undef : res; |
552 | return errflag ? &PL_sv_undef : res; |
539 | } |
553 | } |
540 | |
554 | |
… | |
… | |
588 | { "ASN_COUNTER32", ASN_COUNTER32 }, |
602 | { "ASN_COUNTER32", ASN_COUNTER32 }, |
589 | { "ASN_UNSIGNED32", ASN_UNSIGNED32 }, |
603 | { "ASN_UNSIGNED32", ASN_UNSIGNED32 }, |
590 | { "ASN_TIMETICKS", ASN_TIMETICKS }, |
604 | { "ASN_TIMETICKS", ASN_TIMETICKS }, |
591 | { "ASN_OPAQUE", ASN_OPAQUE }, |
605 | { "ASN_OPAQUE", ASN_OPAQUE }, |
592 | { "ASN_COUNTER64", ASN_COUNTER64 }, |
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 }, |
593 | }; |
612 | }; |
594 | |
613 | |
595 | for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--) |
614 | for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--) |
596 | newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv)); |
615 | newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv)); |
597 | |
616 | |
… | |
… | |
603 | CODE: |
622 | CODE: |
604 | cv = x_get_cv (cv); |
623 | cv = x_get_cv (cv); |
605 | assert (SvTYPE (cv) == SVt_PVCV); |
624 | assert (SvTYPE (cv) == SVt_PVCV); |
606 | av_store (av_type, type, SvREFCNT_inc_NN (cv)); |
625 | av_store (av_type, type, SvREFCNT_inc_NN (cv)); |
607 | |
626 | |
608 | #if 1 |
|
|
609 | |
|
|
610 | SV * |
627 | SV * |
611 | decode_ber (SV *ber) |
628 | ber_decode (SV *ber) |
612 | CODE: |
629 | CODE: |
613 | { |
630 | { |
614 | clear_bufobj (); |
631 | clear_bufobj (); |
615 | |
632 | |
616 | errflag = 0; |
633 | errflag = 0; |
… | |
… | |
620 | |
637 | |
621 | buf = SvPVbyte (bufsv, len); |
638 | buf = SvPVbyte (bufsv, len); |
622 | cur = buf; |
639 | cur = buf; |
623 | rem = len; |
640 | rem = len; |
624 | |
641 | |
625 | RETVAL = decode_ber (); |
642 | RETVAL = ber_decode (); |
626 | } |
643 | } |
627 | OUTPUT: RETVAL |
644 | OUTPUT: RETVAL |
628 | |
645 | |
629 | #endif |
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 | } |
630 | |
728 | |
631 | MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message |
729 | MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message |
632 | |
730 | |
633 | void |
731 | void |
634 | _buffer_append (BUFOBJ self, SV *value) |
732 | _buffer_append (BUFOBJ self, SV *value) |
… | |
… | |
777 | |
875 | |
778 | SV * |
876 | SV * |
779 | _process_var_bind_list (BUFOBJ self) |
877 | _process_var_bind_list (BUFOBJ self) |
780 | CODE: |
878 | CODE: |
781 | { |
879 | { |
782 | if (get8 () != ASN_SEQUENCE) |
880 | if (get8 () != ASN_SEQUENCE | ASN_CONSTRUCTED) |
783 | error ("SEQUENCE expected at beginning of VarBindList"); |
881 | error ("SEQUENCE expected at beginning of VarBindList"); |
|
|
882 | |
784 | int seqlen = process_length (); |
883 | int seqlen = process_length (); |
785 | U8 *end = cur + seqlen; |
884 | U8 *end = cur + seqlen; |
786 | |
885 | |
787 | HV *list = newHV (); |
886 | HV *list = newHV (); |
788 | AV *names = newAV (); |
887 | AV *names = newAV (); |
… | |
… | |
793 | hv_store ((HV *)cur_bufobj, "_var_bind_types", sizeof ("_var_bind_types") - 1, newRV_noinc ((SV *)types), 0); |
892 | hv_store ((HV *)cur_bufobj, "_var_bind_types", sizeof ("_var_bind_types") - 1, newRV_noinc ((SV *)types), 0); |
794 | |
893 | |
795 | while (cur < end && !errflag) |
894 | while (cur < end && !errflag) |
796 | { |
895 | { |
797 | // SEQUENCE ObjectName ObjectSyntax |
896 | // SEQUENCE ObjectName ObjectSyntax |
798 | if (get8 () != ASN_SEQUENCE) |
897 | if (get8 () != ASN_SEQUENCE | ASN_CONSTRUCTED) |
799 | error ("SEQUENCE expected at beginning of VarBind"); |
898 | error ("SEQUENCE expected at beginning of VarBind"); |
800 | process_length (); |
899 | process_length (); |
801 | |
900 | |
802 | if (get8 () != ASN_OBJECT_IDENTIFIER) |
901 | if (get8 () != ASN_OBJECT_IDENTIFIER) |
803 | error ("OBJECT IDENTIFIER expected at beginning of VarBind"); |
902 | error ("OBJECT IDENTIFIER expected at beginning of VarBind"); |