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.6 by root, Thu Apr 9 05:56:36 2009 UTC vs.
Revision 1.20 by root, Fri Apr 19 15:50:48 2019 UTC

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 6
7#define ASN_BOOLEAN 0x01
8#define ASN_INTEGER32 0x02
9#define ASN_OCTET_STRING 0x04
10#define ASN_NULL 0x05
11#define ASN_OBJECT_IDENTIFIER 0x06
12#define ASN_SEQUENCE 0x30
13#define ASN_IPADDRESS 0x40
14#define ASN_COUNTER32 0x41
15#define ASN_UNSIGNED32 0x42
16#define ASN_TIMETICKS 0x43
17#define ASN_OPAQUE 0x44
18#define ASN_COUNTER64 0x46
19
20//#define BENCHMARK 7//#define BENCHMARK
21 8
9enum {
10 // ASN_TAG
11 ASN_BOOLEAN = 0x01,
12 ASN_INTEGER32 = 0x02,
13 ASN_BIT_STRING = 0x03,
14 ASN_OCTET_STRING = 0x04,
15 ASN_NULL = 0x05,
16 ASN_OBJECT_IDENTIFIER = 0x06,
17 ASN_SEQUENCE = 0x10,
18
19 ASN_TAG_BER = 0x1f,
20 ASN_TAG_MASK = 0x1f,
21
22 // primitive/constructed
23 ASN_CONSTRUCTED = 0x20,
24
25 // ASN_CLASS
26 ASN_UNIVERSAL = 0x00,
27 ASN_APPLICATION = 0x40,
28 ASN_CONTEXT = 0x80,
29 ASN_PRIVATE = 0xc0,
30
31 ASN_CLASS_MASK = 0xc0,
32 ASN_CLASS_SHIFT = 6,
33
34 // ASN_APPLICATION
35 ASN_IPADDRESS = 0x00,
36 ASN_COUNTER32 = 0x01,
37 ASN_UNSIGNED32 = 0x02,
38 ASN_TIMETICKS = 0x03,
39 ASN_OPAQUE = 0x04,
40 ASN_COUNTER64 = 0x06,
41};
42
43enum {
44 BER_CLASS = 0,
45 BER_TAG = 1,
46 BER_CONSTRUCTED = 2,
47 BER_DATA = 3,
48 BER_ARRAYSIZE
49};
50
22#define MAX_OID_STRLEN 4096 51#define MAX_OID_STRLEN 4096
23 52
53#define HAVE_VERSIONSORT defined (_GNU_SOURCE) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
54
55static SV *cur_bufobj;
24static SV *msg; 56static SV *msg, *bufsv;
25static int errflag, leading_dot; 57static int errflag, leading_dot;
26static U8 *buf, *cur; 58static U8 *buf, *cur;
27static STRLEN len, rem; 59static STRLEN len, rem;
28 60
61typedef SV *BUFOBJ;
62
63// for "small" integers, return a readonly sv, otherwise create a new one
64static 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
80/////////////////////////////////////////////////////////////////////////////
81
82#if 0
83 if (msg)
84 croak ("recursive invocation of Net::SNMP::XS parser is not supported");
85
86
87void
88clr_msg ()
89 CODE:
90 SvREFCNT_dec (msg); msg = 0;
91 buf = cur = (U8 *)"";
92 len = rem = 0;
93#endif
94
95static void
96clear_bufobj (void)
97{
98 // serialise our state back
99 if (msg && SvROK (msg))
100 {
101 SV *idx_sv = *hv_fetch ((HV *)cur_bufobj, "_index" , sizeof ("_index" ) - 1, 1);
102 sv_setiv (idx_sv, cur - buf);
103 }
104
105 SvREFCNT_dec (msg);
106 msg = 0;
107 cur_bufobj = 0;
108}
109
110static void
111switch_bufobj (BUFOBJ neu)
112{
113 clear_bufobj ();
114
115 msg = newSVsv (neu);
116 cur_bufobj = SvRV (msg);
117 sv_rvweaken (msg);
118
119 errflag = 0;
120 leading_dot = -1;
121
122 IV index = SvIV (*hv_fetch ((HV *)cur_bufobj, "_index" , sizeof ("_index" ) - 1, 1));
123 bufsv = *hv_fetch ((HV *)cur_bufobj, "_buffer", sizeof ("_buffer") - 1, 1);
124
125 buf = SvPVbyte (bufsv, len);
126 cur = buf + index;
127 rem = len - index;
128}
129
130/////////////////////////////////////////////////////////////////////////////
131
29static SV * 132static SV *
30x_get_cv (SV *cb_sv) 133x_get_cv (SV *cb_sv)
31{ 134{
32 HV *st; 135 HV *st;
33 GV *gvp; 136 GV *gvp;
38 141
39 return (SV *)cv; 142 return (SV *)cv;
40} 143}
41 144
42static void 145static void
43error (const char *msg) 146error (const char *errmsg)
44{ 147{
45 errflag = 1; 148 errflag = 1;
46 149
47 printf ("<<<%s>>>\n", msg);//D 150 if (!msg)
151 croak ("Net::SNMP::XS fatal error, parser called without parsing context");
152
153 dSP;
154 PUSHMARK (SP);
155 EXTEND (SP, 2);
156 PUSHs (msg);
157 PUSHs (sv_2mortal (newSVpv (errmsg, 0)));
158 PUTBACK;
159 call_method ("_error", G_VOID | G_DISCARD);
48} 160}
49 161
50static int 162static int
51need (int count) 163need (int count)
52{ 164{
183process_unsigned32_sv (void) 295process_unsigned32_sv (void)
184{ 296{
185 return newSVuv ((U32)process_integer32 ()); 297 return newSVuv ((U32)process_integer32 ());
186} 298}
187 299
300#if IVSIZE >= 8
301
302static U64TYPE
303process_integer64 (void)
304{
305 U32 length = process_length ();
306
307 if (length <= 0)
308 {
309 error ("INTEGER64 length equal to zero");
310 return 0;
311 }
312
313 U8 *data = getn (length, 0);
314
315 if (!data)
316 return 0;
317
318 if (length > 9 || (length > 8 && data [0]))
319 {
320 error ("INTEGER64 length too long");
321 return 0;
322 }
323
324 U64TYPE res = data [0] & 0x80 ? 0xffffffffffffffff : 0;
325
326 while (length--)
327 res = (res << 8) | *data++;
328
329 return res;
330}
331
332static SV *
333process_integer64_sv (void)
334{
335 return newSViv ((I64TYPE)process_integer64 ());
336}
337
338static SV *
339process_unsigned64_sv (void)
340{
341 return newSVuv ((U64TYPE)process_integer64 ());
342}
343
344#endif
345
188static SV * 346static SV *
189process_octet_string_sv (void) 347process_octet_string_sv (void)
190{ 348{
191 U32 length = process_length (); 349 U32 length = process_length ();
192 350
210 buf += sprintf (buf, "%u", (unsigned int)u); 368 buf += sprintf (buf, "%u", (unsigned int)u);
211 369
212 return buf; 370 return buf;
213} 371}
214 372
215static char * 373static SV *
216process_object_identifier (int *len) 374process_object_identifier_sv (void)
217{ 375{
218 U32 length = process_length (); 376 U32 length = process_length ();
219 377
220 if (length <= 0) 378 if (length <= 0)
221 { 379 {
222 error ("OBJECT IDENTIFIER length equal to zero"); 380 error ("OBJECT IDENTIFIER length equal to zero");
223 return ""; 381 return &PL_sv_undef;
224 } 382 }
225 383
226 U8 *end = cur + length; 384 U8 *end = cur + length;
227 U32 w = getb (); 385 U32 w = getb ();
228 386
229 static char oid[MAX_OID_STRLEN]; // must be static 387 static char oid[MAX_OID_STRLEN]; // must be static
230 char *app = oid; 388 char *app = oid;
389
390 if (leading_dot < 0)
391 leading_dot = SvTRUE (*hv_fetch ((HV *)SvRV (msg), "_leading_dot", sizeof ("_leading_dot") - 1, 1));
231 392
232 *app = '.'; app += ! ! leading_dot; 393 *app = '.'; app += ! ! leading_dot;
233 app = write_uv (app, (U8)w / 40); 394 app = write_uv (app, (U8)w / 40);
234 *app++ = '.'; 395 *app++ = '.';
235 app = write_uv (app, (U8)w % 40); 396 app = write_uv (app, (U8)w % 40);
240 w = getb (); 401 w = getb ();
241 *app++ = '.'; 402 *app++ = '.';
242 app = write_uv (app, w); 403 app = write_uv (app, w);
243 } 404 }
244 405
245 *len = app - oid;
246 return oid;
247}
248
249static SV *
250process_object_identifier_sv (void)
251{
252 int len;
253 char *oid = process_object_identifier (&len);
254
255 return newSVpvn (oid, len); 406 return newSVpvn (oid, app - oid);
256} 407}
257 408
258static AV *av_type; 409static AV *av_type;
259 410
260static SV * 411static SV *
274 425
275 case ASN_INTEGER32: 426 case ASN_INTEGER32:
276 res = process_integer32_sv (); 427 res = process_integer32_sv ();
277 break; 428 break;
278 429
279 case ASN_UNSIGNED32: 430 case ASN_APPLICATION | ASN_UNSIGNED32:
280 case ASN_COUNTER32: 431 case ASN_APPLICATION | ASN_COUNTER32:
281 case ASN_TIMETICKS: 432 case ASN_APPLICATION | ASN_TIMETICKS:
282 res = process_unsigned32_sv (); 433 res = process_unsigned32_sv ();
283 break; 434 break;
284 435
285 case ASN_SEQUENCE: 436 case ASN_SEQUENCE | ASN_CONSTRUCTED:
286 res = newSVuv (process_length ()); 437 res = newSVuv (process_length ());
287 break; 438 break;
288 439
289 case ASN_OCTET_STRING: 440 case ASN_OCTET_STRING:
290 case ASN_OPAQUE: 441 case ASN_APPLICATION | ASN_OPAQUE:
291 res = process_octet_string_sv (); 442 res = process_octet_string_sv ();
292 break; 443 break;
293 444
294 default: 445 default:
295 { 446 {
296 if (type > AvFILLp (av_type) || !SvTYPE (AvARRAY (av_type)[type]) == SVt_PVCV) 447 if (type > AvFILLp (av_type)
448 || AvARRAY (av_type)[type] == 0
449 || AvARRAY (av_type)[type] == &PL_sv_undef)
297 { 450 {
298 error ("Unknown ASN.1 type"); 451 error ("Unknown ASN.1 type");
299 return &PL_sv_undef; 452 return &PL_sv_undef;
300 } 453 }
301 454
312 } 465 }
313 466
314 return errflag ? &PL_sv_undef : res; 467 return errflag ? &PL_sv_undef : res;
315} 468}
316 469
470static SV *
471ber_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/////////////////////////////////////////////////////////////////////////////
556
557#if HAVE_VERSIONSORT
558
559static int
560oid_lex_cmp (const void *a_, const void *b_)
561{
562 const char *a = SvPVX (*(SV **)a_);
563 const char *b = SvPVX (*(SV **)b_);
564
565 a += *a == '.';
566 b += *b == '.';
567
568 return strverscmp (a, b);
569}
570
571#endif
572
317MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS 573MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS
318 574
319PROTOTYPES: ENABLE 575PROTOTYPES: ENABLE
320 576
321BOOT: 577BOOT:
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
322 av_type = newAV (); 617 av_type = newAV ();
618}
323 619
324void 620void
325set_type (int type, SV *cv) 621set_type (int type, SV *cv)
326 CODE: 622 CODE:
623 cv = x_get_cv (cv);
624 assert (SvTYPE (cv) == SVt_PVCV);
327 av_store (av_type, type, SvREFCNT_inc (x_get_cv (cv))); 625 av_store (av_type, type, SvREFCNT_inc_NN (cv));
626
627SV *
628ber_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
328 645
329void 646void
330set_msg (SV *msg_, SV *buf_) 647ber_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: $;$$$
331 CODE: 649 PPCODE:
332 errflag = 0; 650{
333 leading_dot = -1; 651 if (!SvOK (tuple))
334 msg = SvREFCNT_inc (msg_); 652 XSRETURN_NO;
335 buf = SvPVbyte (buf_, len); 653
336 cur = buf; 654 if (!SvROK (tuple) || SvTYPE (SvRV (tuple)) != SVt_PVAV)
337 rem = len; 655 croak ("ber_seq: tuple must be ber tuple (array-ref)");
338#ifdef BENCHMARK 656
339 t1 = tstamp (); 657 AV *av = (AV *)SvRV (tuple);
340#endif 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}
341 666
342void 667void
343clr_msg () 668ber_seq (SV *tuple)
669 PROTOTYPE: $
344 CODE: 670 PPCODE:
345 SvREFCNT_dec (msg); 671{
346 buf = cur = ""; 672 if (!SvOK (tuple))
347 len = rem = 0; 673 XSRETURN_UNDEF;
348#ifdef BENCHMARK 674
349 printf ("%f\n", tstamp () - t1);//D 675 if (!SvROK (tuple) || SvTYPE (SvRV (tuple)) != SVt_PVAV)
350#endif 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
687void
688ber_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
708void
709ber_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}
351 728
352MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message 729MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message
353 730
354void 731void
732_buffer_append (BUFOBJ self, SV *value)
733 ALIAS:
734 _buffer_put = 1
735 PPCODE:
736{
737 STRLEN vlen;
738 const char *vstr = SvPVbyte (value, vlen);
739
740 if (ix)
741 sv_insert (bufsv, 0, 0, vstr, vlen);
742 else
743 sv_catpvn (bufsv, vstr, vlen);
744
745 buf = SvPVbyte (bufsv, len);
746 cur = buf;
747 rem = len;
748
749 SV *len_sv = *hv_fetch ((HV *)cur_bufobj, "_length", sizeof ("_length") - 1, 1);
750 sv_setiv (len_sv, len);
751
752 // some callers test for defined'ness of the returnvalue. *sigh*
753 XPUSHs (&PL_sv_yes);
754}
755
756void
355_buffer_get (SV *self, int count = -1) 757_buffer_get (BUFOBJ self, int count = -1)
356 PPCODE: 758 PPCODE:
357{ 759{
358 // grrr. 760 // grrr.
359 if (count < 0) 761 if (count < 0)
360 { 762 {
361 hv_delete ((HV *)SvRV (self), "_index" , 6, G_DISCARD); 763 hv_delete ((HV *)SvRV (self), "_index" , 6, G_DISCARD);
362 hv_delete ((HV *)SvRV (self), "_length", 7, G_DISCARD); 764 hv_delete ((HV *)SvRV (self), "_length", 7, G_DISCARD);
363 SV **svp = hv_fetch ((HV *)SvRV (self), "_buffer", 7, 1);
364 XPUSHs (sv_2mortal (newSVsv (*svp))); 765 XPUSHs (sv_2mortal (newSVsv (bufsv)));
365 sv_setpvn (*svp, "", 0); 766 sv_setpvn (bufsv, "", 0);
767
768 buf = "";
769 cur = buf;
770 rem = 0;
771
366 XSRETURN (1); 772 XSRETURN (1);
367 } 773 }
368 774
369 char *data = getn (count, 0); 775 char *data = getn (count, 0);
370 776
371 if (data) 777 if (data)
372 XPUSHs (sv_2mortal (newSVpvn (data, count))); 778 XPUSHs (sv_2mortal (newSVpvn (data, count)));
373} 779}
374 780
375U32 781U32
376index (SV *self, int ndx = -1) 782index (BUFOBJ self, int ndx = -1)
377 CODE: 783 CODE:
378{ 784{
379 if (ndx >= 0 && ndx < len) 785 if (ndx >= 0 && ndx < len)
380 { 786 {
381 cur = buf + ndx; 787 cur = buf + ndx;
382 rem = len - ndx; 788 rem = len - ndx;
383 } 789 }
384 790
385 RETVAL = cur - buf; 791 RETVAL = cur - buf;
386} 792}
387 OUTPUT: 793 OUTPUT: RETVAL
388 RETVAL
389 794
390U32 795U32
391_process_length (SV *self, ...) 796_process_length (BUFOBJ self, ...)
392 ALIAS: 797 ALIAS:
393 _process_sequence = 0 798 _process_sequence = 0
394 CODE: 799 CODE:
395 RETVAL = process_length (); 800 RETVAL = process_length ();
396 OUTPUT: 801 OUTPUT: RETVAL
397 RETVAL
398 802
399SV * 803SV *
400_process_integer32 (SV *self, ...) 804_process_integer32 (BUFOBJ self, ...)
401 CODE: 805 CODE:
402 RETVAL = process_integer32_sv (); 806 RETVAL = process_integer32_sv ();
403 OUTPUT: 807 OUTPUT: RETVAL
404 RETVAL
405 808
406SV * 809SV *
407_process_counter (SV *self, ...) 810_process_counter (BUFOBJ self, ...)
408 ALIAS: 811 ALIAS:
409 _process_gauge = 0 812 _process_gauge = 0
410 _process_timeticks = 0 813 _process_timeticks = 0
411 CODE: 814 CODE:
412 RETVAL = process_unsigned32_sv (); 815 RETVAL = process_unsigned32_sv ();
413 OUTPUT: 816 OUTPUT: RETVAL
414 RETVAL 817
818#if IVSIZE >= 8
415 819
416SV * 820SV *
821_process_counter64 (BUFOBJ self, ...)
822 CODE:
823 RETVAL = process_unsigned64_sv ();
824 OUTPUT: RETVAL
825
826#endif
827
828SV *
417_process_object_identifier (SV *self, ...) 829_process_object_identifier (BUFOBJ self, ...)
418 CODE: 830 CODE:
419 RETVAL = process_object_identifier_sv (); 831 RETVAL = process_object_identifier_sv ();
420 OUTPUT: 832 OUTPUT: RETVAL
421 RETVAL
422 833
423SV * 834SV *
424_process_octet_string (SV *self, ...) 835_process_octet_string (BUFOBJ self, ...)
425 ALIAS: 836 ALIAS:
426 _process_opaque = 0 837 _process_opaque = 0
427 CODE: 838 CODE:
428 RETVAL = process_octet_string_sv (); 839 RETVAL = process_octet_string_sv ();
429 OUTPUT: 840 OUTPUT: RETVAL
430 RETVAL
431 841
432SV * 842SV *
433_process_ipaddress (SV *self, ...) 843_process_ipaddress (BUFOBJ self, ...)
434 CODE: 844 CODE:
435{ 845{
436 U32 length = process_length (); 846 U32 length = process_length ();
437 if (length != 4) 847 if (length != 4)
438 { 848 {
439 error ("IP ADDRESS length not four"); 849 error ("IP ADDRESS length not four");
440 XSRETURN_UNDEF; 850 XSRETURN_UNDEF;
441 } 851 }
442 852
443 U8 *data = getn (4, "\x00\x00\x00\x00"); 853 U8 *data = getn (4, "\x00\x00\x00\x00");
444 RETVAL = newSVpvf ("%d.%d.%d.%d", data [0], data [1], data [2], data [3]); 854 RETVAL = newSVpvf ("%d.%d.%d.%d", data [0], data [1], data [2], data [3]);
445} 855}
446 OUTPUT: 856 OUTPUT: RETVAL
447 RETVAL
448 857
449SV * 858SV *
450process (SV *self, SV *expected = &PL_sv_undef, SV *found = 0) 859process (BUFOBJ self, SV *expected = &PL_sv_undef, SV *found = 0)
451 CODE: 860 CODE:
452{ 861{
453 int type; 862 int type;
454 863
455 RETVAL = process_sv (&type); 864 RETVAL = process_sv (&type);
456 865
457 if (found) 866 if (found)
458 sv_setiv (found, type); 867 sv_setiv (found, type);
459 868
460 if (SvOK (expected) && type != SvIV (expected)) 869 if (SvOK (expected) && type != SvIV (expected))
461 error ("Expected a different type than found"); 870 error ("Expected a different type than found");
462} 871}
463 OUTPUT: 872 OUTPUT: RETVAL
464 RETVAL
465 873
466MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::PDU 874MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::PDU
467 875
468SV * 876SV *
469_process_var_bind_list (SV *self) 877_process_var_bind_list (BUFOBJ self)
470 CODE: 878 CODE:
471{ 879{
472 if (get8 () != ASN_SEQUENCE) 880 if (get8 () != ASN_SEQUENCE | ASN_CONSTRUCTED)
473 error ("SEQUENCE expected at beginning of VarBindList"); 881 error ("SEQUENCE expected at beginning of VarBindList");
882
474 int seqlen = process_length (); 883 int seqlen = process_length ();
475 U8 *end = cur + seqlen; 884 U8 *end = cur + seqlen;
476 885
477 HV *list = newHV (); 886 HV *list = newHV ();
478 AV *names = newAV (); 887 AV *names = newAV ();
479 HV *types = newHV (); 888 HV *types = newHV ();
480 889
481 hv_store ((HV *)SvRV (self), "_var_bind_list" , sizeof ("_var_bind_list" ) - 1, newRV_noinc ((SV *)list ), 0); 890 hv_store ((HV *)cur_bufobj, "_var_bind_list" , sizeof ("_var_bind_list" ) - 1, newRV_noinc ((SV *)list ), 0);
482 hv_store ((HV *)SvRV (self), "_var_bind_names", sizeof ("_var_bind_names") - 1, newRV_noinc ((SV *)names), 0); 891 hv_store ((HV *)cur_bufobj, "_var_bind_names", sizeof ("_var_bind_names") - 1, newRV_noinc ((SV *)names), 0);
483 hv_store ((HV *)SvRV (self), "_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);
484 893
485 while (cur < end && !errflag) 894 while (cur < end && !errflag)
486 { 895 {
487 // SEQUENCE ObjectName ObjectSyntax 896 // SEQUENCE ObjectName ObjectSyntax
488 if (get8 () != ASN_SEQUENCE) 897 if (get8 () != ASN_SEQUENCE | ASN_CONSTRUCTED)
489 error ("SEQUENCE expected at beginning of VarBind"); 898 error ("SEQUENCE expected at beginning of VarBind");
490 process_length (); 899 process_length ();
491 900
492 if (get8 () != ASN_OBJECT_IDENTIFIER) 901 if (get8 () != ASN_OBJECT_IDENTIFIER)
493 error ("OBJECT IDENTIFIER expected at beginning of VarBind"); 902 error ("OBJECT IDENTIFIER expected at beginning of VarBind");
494 int type, oidlen; 903 int type, oidlen;
495 char *oid = process_object_identifier (&oidlen); 904 SV *oid = process_object_identifier_sv ();
496 SV *val = process_sv (&type); 905 SV *val = process_sv (&type);
497 906
498 hv_store (types, oid, oidlen, newSViv (type), 0); 907 hv_store_ent (types, oid, newSViv (type), 0);
499 hv_store (list , oid, oidlen, val, 0); 908 hv_store_ent (list , oid, val, 0);
500 av_push (names, newSVpvn (oid, oidlen)); 909 av_push (names, oid);
501 } 910 }
502 911
503 //return $this->_report_pdu_error if ($this->{_pdu_type} == REPORT); 912 // sigh - great design to do it here
913 SV *pdu_type = *hv_fetch ((HV *)cur_bufobj, "_pdu_type" , sizeof ("_pdu_type" ) - 1, 1);
914
915 if (SvIV (pdu_type) == 0xa8) // REPORT
916 {
917 PUSHMARK (SP);
918 XPUSHs (msg);
919 PUTBACK;
920 call_method ("_report_pdu_error", G_VOID | G_DISCARD);
921 SPAGAIN;
922 XSRETURN_EMPTY;
923 }
504 924
505 RETVAL = newRV_inc ((SV *)list); 925 RETVAL = newRV_inc ((SV *)list);
506} 926}
507 OUTPUT: 927 OUTPUT: RETVAL
928
929MODULE = Net::SNMP::XS PACKAGE = Net::SNMP
930
931void
932oid_base_match (SV *base_, SV *oid_)
933 PROTOTYPE: $$
934 ALIAS:
935 oid_context_match = 0
936 PPCODE:
937{
938 if (!SvOK (base_) || !SvOK (oid_))
939 XSRETURN_NO;
940
941 STRLEN blen, olen;
942 char *base = SvPVbyte (base_, blen);
943 char *oid = SvPVbyte (oid_ , olen);
944
945 blen -= *base == '.'; base += *base == '.';
946 olen -= *base == '.'; oid += *oid == '.';
947
948 if (olen < blen)
949 XSRETURN_NO;
950
951 if (memcmp (base, oid, blen))
952 XSRETURN_NO;
953
954 if (oid [blen] && oid [blen] != '.')
955 XSRETURN_NO;
956
957 XSRETURN_YES;
958}
959
960#if HAVE_VERSIONSORT
961
962void
963oid_lex_sort (...)
964 PROTOTYPE: @
965 PPCODE:
966{
967 // make sure SvPVX is valid
968 int i;
969 for (i = items; i--; )
970 {
971 SV *sv = ST (i);
972
973 if (SvTYPE (sv) < SVt_PV || SvTYPE (sv) == SVt_PVAV && SvTYPE (sv) == SVt_PVHV)
974 SvPV_force_nolen (sv);
975 }
976
977 qsort (&ST (0), items, sizeof (SV *), oid_lex_cmp);
978
979 EXTEND (SP, items);
980 // we cheat somewhat by not returning copies here
981 for (i = 0; i < items; ++i)
982 PUSHs (sv_2mortal (SvREFCNT_inc (ST (i))));
983}
984
985int
986_index_cmp (const char *a, const char *b)
987 PROTOTYPE: $$
988 CODE:
989 RETVAL = strverscmp (a, b);
508 RETVAL 990 OUTPUT: RETVAL
509 991
992#endif
510 993

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines