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.2 by root, Wed Apr 8 10:39:32 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_INTEGER 0x02
9#define ASN_BIT_STR 0x03
10#define ASN_OCTET_STR 0x04
11#define ASN_NULL 0x05
12#define ASN_OBJECT_ID 0x06
13#define ASN_SEQUENCE 0x10
14#define ASN_SET 0x11
15
16#define ASN_UNIVERSAL 0x00
17#define ASN_APPLICATION 0x40
18#define ASN_CONTEXT 0x80
19#define ASN_PRIVATE 0xc0
20
21#define ASN_PRIMITIVE 0x00
22#define ASN_CONSTRUCTOR 0x20
23
24#define ASN_LONG_LEN 0x80
25#define ASN_EXTENSION_ID 0x1f
26#define ASN_BIT8 0x80
27
28//#define BENCHMARK 7//#define BENCHMARK
29 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
51#define MAX_OID_STRLEN 4096
52
53#define HAVE_VERSIONSORT defined (_GNU_SOURCE) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
54
55static SV *cur_bufobj;
30static SV *msg; 56static SV *msg, *bufsv;
31static int errflag; 57static int errflag, leading_dot;
32static U8 *buf, *cur; 58static U8 *buf, *cur;
33static STRLEN len, rem; 59static STRLEN len, rem;
34 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
35static void 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
132static SV *
133x_get_cv (SV *cb_sv)
134{
135 HV *st;
136 GV *gvp;
137 CV *cv = sv_2cv (cb_sv, &st, &gvp, 0);
138
139 if (!cv)
140 croak ("CODE reference expected");
141
142 return (SV *)cv;
143}
144
145static void
36error (const char *msg) 146error (const char *errmsg)
37{ 147{
38 errflag = 1; 148 errflag = 1;
39 149
40 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);
41} 160}
42 161
43static int 162static int
44need (int count) 163need (int count)
45{ 164{
134 } 253 }
135 254
136 return res; 255 return res;
137} 256}
138 257
258static U32
259process_integer32 (void)
260{
261 U32 length = process_length ();
262
263 if (length <= 0)
264 {
265 error ("INTEGER32 length equal to zero");
266 return 0;
267 }
268
269 U8 *data = getn (length, 0);
270
271 if (!data)
272 return 0;
273
274 if (length > 5 || (length > 4 && data [0]))
275 {
276 error ("INTEGER32 length too long");
277 return 0;
278 }
279
280 U32 res = data [0] & 0x80 ? 0xffffffff : 0;
281
282 while (length--)
283 res = (res << 8) | *data++;
284
285 return res;
286}
287
288static SV *
289process_integer32_sv (void)
290{
291 return newSViv ((I32)process_integer32 ());
292}
293
294static SV *
295process_unsigned32_sv (void)
296{
297 return newSVuv ((U32)process_integer32 ());
298}
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
346static SV *
347process_octet_string_sv (void)
348{
349 U32 length = process_length ();
350
351 U8 *data = getn (length, 0);
352 if (!data)
353 {
354 error ("OCTET STRING too long");
355 return &PL_sv_undef;
356 }
357
358 return newSVpvn (data, length);
359}
360
361static char *
362write_uv (char *buf, U32 u)
363{
364 // the one-digit case is absolutely predominant
365 if (u < 10)
366 *buf++ = u + '0';
367 else
368 buf += sprintf (buf, "%u", (unsigned int)u);
369
370 return buf;
371}
372
373static SV *
374process_object_identifier_sv (void)
375{
376 U32 length = process_length ();
377
378 if (length <= 0)
379 {
380 error ("OBJECT IDENTIFIER length equal to zero");
381 return &PL_sv_undef;
382 }
383
384 U8 *end = cur + length;
385 U32 w = getb ();
386
387 static char oid[MAX_OID_STRLEN]; // must be static
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));
392
393 *app = '.'; app += ! ! leading_dot;
394 app = write_uv (app, (U8)w / 40);
395 *app++ = '.';
396 app = write_uv (app, (U8)w % 40);
397
398 // we assume an oid component is never > 64 bytes
399 while (cur < end && oid + sizeof (oid) - app > 64)
400 {
401 w = getb ();
402 *app++ = '.';
403 app = write_uv (app, w);
404 }
405
406 return newSVpvn (oid, app - oid);
407}
408
409static AV *av_type;
410
411static SV *
412process_sv (int *found)
413{
414 int type = get8 ();
415
416 *found = type;
417
418 SV *res;
419
420 switch (type)
421 {
422 case ASN_OBJECT_IDENTIFIER:
423 res = process_object_identifier_sv ();
424 break;
425
426 case ASN_INTEGER32:
427 res = process_integer32_sv ();
428 break;
429
430 case ASN_APPLICATION | ASN_UNSIGNED32:
431 case ASN_APPLICATION | ASN_COUNTER32:
432 case ASN_APPLICATION | ASN_TIMETICKS:
433 res = process_unsigned32_sv ();
434 break;
435
436 case ASN_SEQUENCE | ASN_CONSTRUCTED:
437 res = newSVuv (process_length ());
438 break;
439
440 case ASN_OCTET_STRING:
441 case ASN_APPLICATION | ASN_OPAQUE:
442 res = process_octet_string_sv ();
443 break;
444
445 default:
446 {
447 if (type > AvFILLp (av_type)
448 || AvARRAY (av_type)[type] == 0
449 || AvARRAY (av_type)[type] == &PL_sv_undef)
450 {
451 error ("Unknown ASN.1 type");
452 return &PL_sv_undef;
453 }
454
455 dSP;
456 PUSHMARK (SP);
457 EXTEND (SP, 2);
458 PUSHs (msg);
459 PUSHs (sv_2mortal (newSViv (type)));
460 PUTBACK;
461 int count = call_sv (AvARRAY (av_type)[type], G_SCALAR);
462 SPAGAIN;
463 res = count ? SvREFCNT_inc (TOPs) : &PL_sv_undef;
464 }
465 }
466
467 return errflag ? &PL_sv_undef : res;
468}
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
139MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS 573MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS
140 574
575PROTOTYPES: ENABLE
576
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
617 av_type = newAV ();
618}
619
141void 620void
142set_msg (SV *msg_, SV *buf_) 621set_type (int type, SV *cv)
143 CODE: 622 CODE:
623 cv = x_get_cv (cv);
624 assert (SvTYPE (cv) == SVt_PVCV);
625 av_store (av_type, type, SvREFCNT_inc_NN (cv));
626
627SV *
628ber_decode (SV *ber)
629 CODE:
630{
631 clear_bufobj ();
632
144 errflag = 0; 633 errflag = 0;
145 msg = SvREFCNT_inc (msg_); 634 leading_dot = 0;
635
636 bufsv = ber;
637
146 buf = SvPVbyte (buf_, len); 638 buf = SvPVbyte (bufsv, len);
147 cur = buf; 639 cur = buf;
148 rem = len; 640 rem = len;
149#ifdef BENCHMARK 641
150 t1 = tstamp (); 642 RETVAL = ber_decode ();
151#endif 643}
644 OUTPUT: RETVAL
152 645
153void 646void
154clr_msg () 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: $;$$$
155 CODE: 649 PPCODE:
156 SvREFCNT_dec (msg); 650{
157 buf = cur = ""; 651 if (!SvOK (tuple))
158 len = rem = 0; 652 XSRETURN_NO;
159#ifdef BENCHMARK 653
160 printf ("%f\n", tstamp () - t1);//D 654 if (!SvROK (tuple) || SvTYPE (SvRV (tuple)) != SVt_PVAV)
161#endif 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
667void
668ber_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
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}
162 728
163MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message 729MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message
164 730
165void 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
166_buffer_get (SV *self, int count = -1) 757_buffer_get (BUFOBJ self, int count = -1)
167 PPCODE: 758 PPCODE:
168{ 759{
169 // grrr. 760 // grrr.
170 if (count < 0) 761 if (count < 0)
171 { 762 {
172 hv_delete ((HV *)SvRV (self), "_index" , 6, G_DISCARD); 763 hv_delete ((HV *)SvRV (self), "_index" , 6, G_DISCARD);
173 hv_delete ((HV *)SvRV (self), "_length", 7, G_DISCARD); 764 hv_delete ((HV *)SvRV (self), "_length", 7, G_DISCARD);
174 SV **svp = hv_fetch ((HV *)SvRV (self), "_buffer", 7, 1);
175 XPUSHs (sv_2mortal (newSVsv (*svp))); 765 XPUSHs (sv_2mortal (newSVsv (bufsv)));
176 sv_setpvn (*svp, "", 0); 766 sv_setpvn (bufsv, "", 0);
767
768 buf = "";
769 cur = buf;
770 rem = 0;
771
177 XSRETURN (1); 772 XSRETURN (1);
178 } 773 }
179 774
180 char *data = getn (count, 0); 775 char *data = getn (count, 0);
181 776
182 if (data) 777 if (data)
183 XPUSHs (sv_2mortal (newSVpvn (data, count))); 778 XPUSHs (sv_2mortal (newSVpvn (data, count)));
184} 779}
185 780
186U32 781U32
187index (SV *self, int ndx = -1) 782index (BUFOBJ self, int ndx = -1)
188 CODE: 783 CODE:
189{ 784{
190 if (ndx >= 0 && ndx < len) 785 if (ndx >= 0 && ndx < len)
191 { 786 {
192 cur = buf + ndx; 787 cur = buf + ndx;
193 rem = len - ndx; 788 rem = len - ndx;
194 } 789 }
195 790
196 RETVAL = cur - buf; 791 RETVAL = cur - buf;
197} 792}
198 OUTPUT: 793 OUTPUT: RETVAL
199 RETVAL
200 794
201U32 795U32
202_process_length (SV *self, ...) 796_process_length (BUFOBJ self, ...)
203 ALIAS: 797 ALIAS:
204 _process_sequence = 1 798 _process_sequence = 0
205 CODE: 799 CODE:
206 RETVAL = process_length (); 800 RETVAL = process_length ();
207 OUTPUT: 801 OUTPUT: RETVAL
208 RETVAL
209 802
210I32 803SV *
211_process_integer32 (SV *self, ...) 804_process_integer32 (BUFOBJ self, ...)
805 CODE:
806 RETVAL = process_integer32_sv ();
807 OUTPUT: RETVAL
808
809SV *
810_process_counter (BUFOBJ self, ...)
212 ALIAS: 811 ALIAS:
213 _process_counter = 0
214 _process_gauge = 0 812 _process_gauge = 0
813 _process_timeticks = 0
215 CODE: 814 CODE:
216{ 815 RETVAL = process_unsigned32_sv ();
217 U32 length = process_length (); 816 OUTPUT: RETVAL
218 817
219 if (length <= 0) 818#if IVSIZE >= 8
220 {
221 error ("INTEGER32 length equal to zero");
222 XSRETURN_UNDEF;
223 }
224
225 U8 *data = getn (length, 0);
226
227 if (!data)
228 XSRETURN_UNDEF;
229
230 if (length > 5 || (length > 4 && data [0]))
231 {
232 error ("INTEGER32 length too long");
233 XSRETURN_UNDEF;
234 }
235
236 U32 res = data [0] & 0x80 ? 0xffffffff : 0;
237
238 while (length--)
239 res = (res << 8) | *data++;
240
241 RETVAL = res;
242}
243 OUTPUT:
244 RETVAL
245 819
246SV * 820SV *
247_process_object_identifier (SV *self, ...) 821_process_counter64 (BUFOBJ self, ...)
248 CODE: 822 CODE:
249{ 823 RETVAL = process_unsigned64_sv ();
250 U32 length = process_length (); 824 OUTPUT: RETVAL
251 825
252 if (length <= 0) 826#endif
253 {
254 error ("OBJECT IDENTIFIER length equal to zero");
255 XSRETURN_UNDEF;
256 }
257
258 U8 *end = cur + length;
259 U32 w = getb ();
260
261 //TODO: leading_dots
262
263 RETVAL = newSVpvf (".%d.%d", (int)w / 40, (int)w % 40);
264
265 while (cur < end)
266 {
267 w = getb ();
268 sv_catpvf (RETVAL, ".%u", (unsigned int)w);
269 }
270}
271 OUTPUT:
272 RETVAL
273 827
274SV * 828SV *
829_process_object_identifier (BUFOBJ self, ...)
830 CODE:
831 RETVAL = process_object_identifier_sv ();
832 OUTPUT: RETVAL
833
834SV *
275_process_octet_string (SV *self, ...) 835_process_octet_string (BUFOBJ self, ...)
276 ALIAS: 836 ALIAS:
277 _process_opaque = 0 837 _process_opaque = 0
278 CODE: 838 CODE:
279{ 839 RETVAL = process_octet_string_sv ();
280 U32 length = process_length (); 840 OUTPUT: RETVAL
281
282 U8 *data = getn (length, 0);
283 if (!data)
284 {
285 error ("OCTET STRING too long");
286 XSRETURN_UNDEF;
287 }
288
289 RETVAL = newSVpvn (data, length);
290}
291 OUTPUT:
292 RETVAL
293 841
294SV * 842SV *
295_process_ipaddress (SV *self, ...) 843_process_ipaddress (BUFOBJ self, ...)
296 CODE: 844 CODE:
297{ 845{
298 U32 length = process_length (); 846 U32 length = process_length ();
299 if (length != 4) 847 if (length != 4)
300 { 848 {
301 error ("IP ADDRESS length not four"); 849 error ("IP ADDRESS length not four");
302 XSRETURN_UNDEF; 850 XSRETURN_UNDEF;
303 } 851 }
304 852
305 U8 *data = getn (4, "\x00\x00\x00\x00"); 853 U8 *data = getn (4, "\x00\x00\x00\x00");
306 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]);
307} 855}
308 OUTPUT: 856 OUTPUT: RETVAL
857
858SV *
859process (BUFOBJ self, SV *expected = &PL_sv_undef, SV *found = 0)
860 CODE:
861{
862 int type;
863
864 RETVAL = process_sv (&type);
865
866 if (found)
867 sv_setiv (found, type);
868
869 if (SvOK (expected) && type != SvIV (expected))
870 error ("Expected a different type than found");
871}
872 OUTPUT: RETVAL
873
874MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::PDU
875
876SV *
877_process_var_bind_list (BUFOBJ self)
878 CODE:
879{
880 if (get8 () != ASN_SEQUENCE | ASN_CONSTRUCTED)
881 error ("SEQUENCE expected at beginning of VarBindList");
882
883 int seqlen = process_length ();
884 U8 *end = cur + seqlen;
885
886 HV *list = newHV ();
887 AV *names = newAV ();
888 HV *types = newHV ();
889
890 hv_store ((HV *)cur_bufobj, "_var_bind_list" , sizeof ("_var_bind_list" ) - 1, newRV_noinc ((SV *)list ), 0);
891 hv_store ((HV *)cur_bufobj, "_var_bind_names", sizeof ("_var_bind_names") - 1, newRV_noinc ((SV *)names), 0);
892 hv_store ((HV *)cur_bufobj, "_var_bind_types", sizeof ("_var_bind_types") - 1, newRV_noinc ((SV *)types), 0);
893
894 while (cur < end && !errflag)
895 {
896 // SEQUENCE ObjectName ObjectSyntax
897 if (get8 () != ASN_SEQUENCE | ASN_CONSTRUCTED)
898 error ("SEQUENCE expected at beginning of VarBind");
899 process_length ();
900
901 if (get8 () != ASN_OBJECT_IDENTIFIER)
902 error ("OBJECT IDENTIFIER expected at beginning of VarBind");
903 int type, oidlen;
904 SV *oid = process_object_identifier_sv ();
905 SV *val = process_sv (&type);
906
907 hv_store_ent (types, oid, newSViv (type), 0);
908 hv_store_ent (list , oid, val, 0);
909 av_push (names, oid);
910 }
911
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 }
924
925 RETVAL = newRV_inc ((SV *)list);
926}
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);
309 RETVAL 990 OUTPUT: RETVAL
310 991
992#endif
993

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines