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.17 by root, Thu Dec 29 22:35:23 2016 UTC

1#include "EXTERN.h" 1#include "EXTERN.h"
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
7//#define BENCHMARK
6 8
7#define ASN_BOOLEAN 0x01 9#define ASN_BOOLEAN 0x01
8#define ASN_INTEGER32 0x02 10#define ASN_INTEGER32 0x02
9#define ASN_OCTET_STRING 0x04 11#define ASN_OCTET_STRING 0x04
10#define ASN_NULL 0x05 12#define ASN_NULL 0x05
15#define ASN_UNSIGNED32 0x42 17#define ASN_UNSIGNED32 0x42
16#define ASN_TIMETICKS 0x43 18#define ASN_TIMETICKS 0x43
17#define ASN_OPAQUE 0x44 19#define ASN_OPAQUE 0x44
18#define ASN_COUNTER64 0x46 20#define ASN_COUNTER64 0x46
19 21
20//#define BENCHMARK
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
26static SV *cur_bufobj;
24static SV *msg; 27static SV *msg, *bufsv;
25static int errflag, leading_dot; 28static int errflag, leading_dot;
26static U8 *buf, *cur; 29static U8 *buf, *cur;
27static STRLEN len, rem; 30static STRLEN len, rem;
28 31
32typedef 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
41void
42clr_msg ()
43 CODE:
44 SvREFCNT_dec (msg); msg = 0;
45 buf = cur = (U8 *)"";
46 len = rem = 0;
47#endif
48
49static void
50clear_bufobj (void)
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 = 0;
61 cur_bufobj = 0;
62}
63
64static void
65switch_bufobj (BUFOBJ neu)
66{
67 clear_bufobj ();
68
69 msg = newSVsv (neu);
70 cur_bufobj = SvRV (msg);
71 sv_rvweaken (msg);
72
73 errflag = 0;
74 leading_dot = -1;
75
76 IV index = SvIV (*hv_fetch ((HV *)cur_bufobj, "_index" , sizeof ("_index" ) - 1, 1));
77 bufsv = *hv_fetch ((HV *)cur_bufobj, "_buffer", sizeof ("_buffer") - 1, 1);
78
79 buf = SvPVbyte (bufsv, len);
80 cur = buf + index;
81 rem = len - index;
82}
83
84/////////////////////////////////////////////////////////////////////////////
85
29static SV * 86static SV *
30x_get_cv (SV *cb_sv) 87x_get_cv (SV *cb_sv)
31{ 88{
32 HV *st; 89 HV *st;
33 GV *gvp; 90 GV *gvp;
38 95
39 return (SV *)cv; 96 return (SV *)cv;
40} 97}
41 98
42static void 99static void
43error (const char *msg) 100error (const char *errmsg)
44{ 101{
45 errflag = 1; 102 errflag = 1;
46 103
47 printf ("<<<%s>>>\n", msg);//D 104 if (!msg)
105 croak ("Net::SNMP::XS fatal error, parser called without parsing context");
106
107 dSP;
108 PUSHMARK (SP);
109 EXTEND (SP, 2);
110 PUSHs (msg);
111 PUSHs (sv_2mortal (newSVpv (errmsg, 0)));
112 PUTBACK;
113 call_method ("_error", G_VOID | G_DISCARD);
48} 114}
49 115
50static int 116static int
51need (int count) 117need (int count)
52{ 118{
183process_unsigned32_sv (void) 249process_unsigned32_sv (void)
184{ 250{
185 return newSVuv ((U32)process_integer32 ()); 251 return newSVuv ((U32)process_integer32 ());
186} 252}
187 253
254#if IVSIZE >= 8
255
256static U64TYPE
257process_integer64 (void)
258{
259 U32 length = process_length ();
260
261 if (length <= 0)
262 {
263 error ("INTEGER64 length equal to zero");
264 return 0;
265 }
266
267 U8 *data = getn (length, 0);
268
269 if (!data)
270 return 0;
271
272 if (length > 9 || (length > 8 && data [0]))
273 {
274 error ("INTEGER64 length too long");
275 return 0;
276 }
277
278 U64TYPE res = data [0] & 0x80 ? 0xffffffffffffffff : 0;
279
280 while (length--)
281 res = (res << 8) | *data++;
282
283 return res;
284}
285
286static SV *
287process_integer64_sv (void)
288{
289 return newSViv ((I64TYPE)process_integer64 ());
290}
291
292static SV *
293process_unsigned64_sv (void)
294{
295 return newSVuv ((U64TYPE)process_integer64 ());
296}
297
298#endif
299
188static SV * 300static SV *
189process_octet_string_sv (void) 301process_octet_string_sv (void)
190{ 302{
191 U32 length = process_length (); 303 U32 length = process_length ();
192 304
210 buf += sprintf (buf, "%u", (unsigned int)u); 322 buf += sprintf (buf, "%u", (unsigned int)u);
211 323
212 return buf; 324 return buf;
213} 325}
214 326
215static char * 327static SV *
216process_object_identifier (int *len) 328process_object_identifier_sv (void)
217{ 329{
218 U32 length = process_length (); 330 U32 length = process_length ();
219 331
220 if (length <= 0) 332 if (length <= 0)
221 { 333 {
222 error ("OBJECT IDENTIFIER length equal to zero"); 334 error ("OBJECT IDENTIFIER length equal to zero");
223 return ""; 335 return &PL_sv_undef;
224 } 336 }
225 337
226 U8 *end = cur + length; 338 U8 *end = cur + length;
227 U32 w = getb (); 339 U32 w = getb ();
228 340
229 static char oid[MAX_OID_STRLEN]; // must be static 341 static char oid[MAX_OID_STRLEN]; // must be static
230 char *app = oid; 342 char *app = oid;
343
344 if (leading_dot < 0)
345 leading_dot = SvTRUE (*hv_fetch ((HV *)SvRV (msg), "_leading_dot", sizeof ("_leading_dot") - 1, 1));
231 346
232 *app = '.'; app += ! ! leading_dot; 347 *app = '.'; app += ! ! leading_dot;
233 app = write_uv (app, (U8)w / 40); 348 app = write_uv (app, (U8)w / 40);
234 *app++ = '.'; 349 *app++ = '.';
235 app = write_uv (app, (U8)w % 40); 350 app = write_uv (app, (U8)w % 40);
240 w = getb (); 355 w = getb ();
241 *app++ = '.'; 356 *app++ = '.';
242 app = write_uv (app, w); 357 app = write_uv (app, w);
243 } 358 }
244 359
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); 360 return newSVpvn (oid, app - oid);
256} 361}
257 362
258static AV *av_type; 363static AV *av_type;
259 364
260static SV * 365static SV *
291 res = process_octet_string_sv (); 396 res = process_octet_string_sv ();
292 break; 397 break;
293 398
294 default: 399 default:
295 { 400 {
296 if (type > AvFILLp (av_type) || !SvTYPE (AvARRAY (av_type)[type]) == SVt_PVCV) 401 if (type > AvFILLp (av_type)
402 || AvARRAY (av_type)[type] == 0
403 || AvARRAY (av_type)[type] == &PL_sv_undef)
297 { 404 {
298 error ("Unknown ASN.1 type"); 405 error ("Unknown ASN.1 type");
299 return &PL_sv_undef; 406 return &PL_sv_undef;
300 } 407 }
301 408
312 } 419 }
313 420
314 return errflag ? &PL_sv_undef : res; 421 return errflag ? &PL_sv_undef : res;
315} 422}
316 423
424/////////////////////////////////////////////////////////////////////////////
425
426#if HAVE_VERSIONSORT
427
428static int
429oid_lex_cmp (const void *a_, const void *b_)
430{
431 const char *a = SvPVX (*(SV **)a_);
432 const char *b = SvPVX (*(SV **)b_);
433
434 a += *a == '.';
435 b += *b == '.';
436
437 return strverscmp (a, b);
438}
439
440#endif
441
317MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS 442MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS
318 443
319PROTOTYPES: ENABLE 444PROTOTYPES: ENABLE
320 445
321BOOT: 446BOOT:
322 av_type = newAV (); 447 av_type = newAV ();
323 448
324void 449void
325set_type (int type, SV *cv) 450set_type (int type, SV *cv)
326 CODE: 451 CODE:
452 cv = x_get_cv (cv);
453 assert (SvTYPE (cv) == SVt_PVCV);
327 av_store (av_type, type, SvREFCNT_inc (x_get_cv (cv))); 454 av_store (av_type, type, SvREFCNT_inc_NN (cv));
455
456MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message
328 457
329void 458void
330set_msg (SV *msg_, SV *buf_) 459_buffer_append (BUFOBJ self, SV *value)
460 ALIAS:
461 _buffer_put = 1
331 CODE: 462 PPCODE:
332 errflag = 0; 463{
333 leading_dot = -1; 464 STRLEN vlen;
334 msg = SvREFCNT_inc (msg_); 465 const char *vstr = SvPVbyte (value, vlen);
466
467 if (ix)
468 sv_insert (bufsv, 0, 0, vstr, vlen);
469 else
470 sv_catpvn (bufsv, vstr, vlen);
471
335 buf = SvPVbyte (buf_, len); 472 buf = SvPVbyte (bufsv, len);
336 cur = buf; 473 cur = buf;
337 rem = len; 474 rem = len;
338#ifdef BENCHMARK 475
339 t1 = tstamp (); 476 SV *len_sv = *hv_fetch ((HV *)cur_bufobj, "_length", sizeof ("_length") - 1, 1);
340#endif 477 sv_setiv (len_sv, len);
478
479 // some callers test for defined'ness of the returnvalue. *sigh*
480 XPUSHs (&PL_sv_yes);
481}
341 482
342void 483void
343clr_msg ()
344 CODE:
345 SvREFCNT_dec (msg);
346 buf = cur = "";
347 len = rem = 0;
348#ifdef BENCHMARK
349 printf ("%f\n", tstamp () - t1);//D
350#endif
351
352MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message
353
354void
355_buffer_get (SV *self, int count = -1) 484_buffer_get (BUFOBJ self, int count = -1)
356 PPCODE: 485 PPCODE:
357{ 486{
358 // grrr. 487 // grrr.
359 if (count < 0) 488 if (count < 0)
360 { 489 {
361 hv_delete ((HV *)SvRV (self), "_index" , 6, G_DISCARD); 490 hv_delete ((HV *)SvRV (self), "_index" , 6, G_DISCARD);
362 hv_delete ((HV *)SvRV (self), "_length", 7, G_DISCARD); 491 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))); 492 XPUSHs (sv_2mortal (newSVsv (bufsv)));
365 sv_setpvn (*svp, "", 0); 493 sv_setpvn (bufsv, "", 0);
494
495 buf = "";
496 cur = buf;
497 rem = 0;
498
366 XSRETURN (1); 499 XSRETURN (1);
367 } 500 }
368 501
369 char *data = getn (count, 0); 502 char *data = getn (count, 0);
370 503
371 if (data) 504 if (data)
372 XPUSHs (sv_2mortal (newSVpvn (data, count))); 505 XPUSHs (sv_2mortal (newSVpvn (data, count)));
373} 506}
374 507
375U32 508U32
376index (SV *self, int ndx = -1) 509index (BUFOBJ self, int ndx = -1)
377 CODE: 510 CODE:
378{ 511{
379 if (ndx >= 0 && ndx < len) 512 if (ndx >= 0 && ndx < len)
380 { 513 {
381 cur = buf + ndx; 514 cur = buf + ndx;
386} 519}
387 OUTPUT: 520 OUTPUT:
388 RETVAL 521 RETVAL
389 522
390U32 523U32
391_process_length (SV *self, ...) 524_process_length (BUFOBJ self, ...)
392 ALIAS: 525 ALIAS:
393 _process_sequence = 0 526 _process_sequence = 0
394 CODE: 527 CODE:
395 RETVAL = process_length (); 528 RETVAL = process_length ();
396 OUTPUT: 529 OUTPUT:
397 RETVAL 530 RETVAL
398 531
399SV * 532SV *
400_process_integer32 (SV *self, ...) 533_process_integer32 (BUFOBJ self, ...)
401 CODE: 534 CODE:
402 RETVAL = process_integer32_sv (); 535 RETVAL = process_integer32_sv ();
403 OUTPUT: 536 OUTPUT:
404 RETVAL 537 RETVAL
405 538
406SV * 539SV *
407_process_counter (SV *self, ...) 540_process_counter (BUFOBJ self, ...)
408 ALIAS: 541 ALIAS:
409 _process_gauge = 0 542 _process_gauge = 0
410 _process_timeticks = 0 543 _process_timeticks = 0
411 CODE: 544 CODE:
412 RETVAL = process_unsigned32_sv (); 545 RETVAL = process_unsigned32_sv ();
413 OUTPUT: 546 OUTPUT:
414 RETVAL 547 RETVAL
415 548
549#if IVSIZE >= 8
550
416SV * 551SV *
552_process_counter64 (BUFOBJ self, ...)
553 CODE:
554 RETVAL = process_unsigned64_sv ();
555 OUTPUT:
556 RETVAL
557
558#endif
559
560SV *
417_process_object_identifier (SV *self, ...) 561_process_object_identifier (BUFOBJ self, ...)
418 CODE: 562 CODE:
419 RETVAL = process_object_identifier_sv (); 563 RETVAL = process_object_identifier_sv ();
420 OUTPUT: 564 OUTPUT:
421 RETVAL 565 RETVAL
422 566
423SV * 567SV *
424_process_octet_string (SV *self, ...) 568_process_octet_string (BUFOBJ self, ...)
425 ALIAS: 569 ALIAS:
426 _process_opaque = 0 570 _process_opaque = 0
427 CODE: 571 CODE:
428 RETVAL = process_octet_string_sv (); 572 RETVAL = process_octet_string_sv ();
429 OUTPUT: 573 OUTPUT:
430 RETVAL 574 RETVAL
431 575
432SV * 576SV *
433_process_ipaddress (SV *self, ...) 577_process_ipaddress (BUFOBJ self, ...)
434 CODE: 578 CODE:
435{ 579{
436 U32 length = process_length (); 580 U32 length = process_length ();
437 if (length != 4) 581 if (length != 4)
438 { 582 {
439 error ("IP ADDRESS length not four"); 583 error ("IP ADDRESS length not four");
440 XSRETURN_UNDEF; 584 XSRETURN_UNDEF;
441 } 585 }
445} 589}
446 OUTPUT: 590 OUTPUT:
447 RETVAL 591 RETVAL
448 592
449SV * 593SV *
450process (SV *self, SV *expected = &PL_sv_undef, SV *found = 0) 594process (BUFOBJ self, SV *expected = &PL_sv_undef, SV *found = 0)
451 CODE: 595 CODE:
452{ 596{
453 int type; 597 int type;
454 598
455 RETVAL = process_sv (&type); 599 RETVAL = process_sv (&type);
456 600
457 if (found) 601 if (found)
458 sv_setiv (found, type); 602 sv_setiv (found, type);
464 RETVAL 608 RETVAL
465 609
466MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::PDU 610MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::PDU
467 611
468SV * 612SV *
469_process_var_bind_list (SV *self) 613_process_var_bind_list (BUFOBJ self)
470 CODE: 614 CODE:
471{ 615{
472 if (get8 () != ASN_SEQUENCE) 616 if (get8 () != ASN_SEQUENCE)
473 error ("SEQUENCE expected at beginning of VarBindList"); 617 error ("SEQUENCE expected at beginning of VarBindList");
474 int seqlen = process_length (); 618 int seqlen = process_length ();
476 620
477 HV *list = newHV (); 621 HV *list = newHV ();
478 AV *names = newAV (); 622 AV *names = newAV ();
479 HV *types = newHV (); 623 HV *types = newHV ();
480 624
481 hv_store ((HV *)SvRV (self), "_var_bind_list" , sizeof ("_var_bind_list" ) - 1, newRV_noinc ((SV *)list ), 0); 625 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); 626 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); 627 hv_store ((HV *)cur_bufobj, "_var_bind_types", sizeof ("_var_bind_types") - 1, newRV_noinc ((SV *)types), 0);
484 628
485 while (cur < end && !errflag) 629 while (cur < end && !errflag)
486 { 630 {
487 // SEQUENCE ObjectName ObjectSyntax 631 // SEQUENCE ObjectName ObjectSyntax
488 if (get8 () != ASN_SEQUENCE) 632 if (get8 () != ASN_SEQUENCE)
490 process_length (); 634 process_length ();
491 635
492 if (get8 () != ASN_OBJECT_IDENTIFIER) 636 if (get8 () != ASN_OBJECT_IDENTIFIER)
493 error ("OBJECT IDENTIFIER expected at beginning of VarBind"); 637 error ("OBJECT IDENTIFIER expected at beginning of VarBind");
494 int type, oidlen; 638 int type, oidlen;
495 char *oid = process_object_identifier (&oidlen); 639 SV *oid = process_object_identifier_sv ();
496 SV *val = process_sv (&type); 640 SV *val = process_sv (&type);
497 641
498 hv_store (types, oid, oidlen, newSViv (type), 0); 642 hv_store_ent (types, oid, newSViv (type), 0);
499 hv_store (list , oid, oidlen, val, 0); 643 hv_store_ent (list , oid, val, 0);
500 av_push (names, newSVpvn (oid, oidlen)); 644 av_push (names, oid);
501 } 645 }
502 646
503 //return $this->_report_pdu_error if ($this->{_pdu_type} == REPORT); 647 // sigh - great design to do it here
648 SV *pdu_type = *hv_fetch ((HV *)cur_bufobj, "_pdu_type" , sizeof ("_pdu_type" ) - 1, 1);
649
650 if (SvIV (pdu_type) == 0xa8) // REPORT
651 {
652 PUSHMARK (SP);
653 XPUSHs (msg);
654 PUTBACK;
655 call_method ("_report_pdu_error", G_VOID | G_DISCARD);
656 SPAGAIN;
657 XSRETURN_EMPTY;
658 }
504 659
505 RETVAL = newRV_inc ((SV *)list); 660 RETVAL = newRV_inc ((SV *)list);
506} 661}
507 OUTPUT: 662 OUTPUT:
508 RETVAL 663 RETVAL
509 664
665MODULE = Net::SNMP::XS PACKAGE = Net::SNMP
510 666
667void
668oid_base_match (SV *base_, SV *oid_)
669 PROTOTYPE: $$
670 ALIAS:
671 oid_context_match = 0
672 PPCODE:
673{
674 if (!SvOK (base_) || !SvOK (oid_))
675 XSRETURN_NO;
676
677 STRLEN blen, olen;
678 char *base = SvPVbyte (base_, blen);
679 char *oid = SvPVbyte (oid_ , olen);
680
681 blen -= *base == '.'; base += *base == '.';
682 olen -= *base == '.'; oid += *oid == '.';
683
684 if (olen < blen)
685 XSRETURN_NO;
686
687 if (memcmp (base, oid, blen))
688 XSRETURN_NO;
689
690 if (oid [blen] && oid [blen] != '.')
691 XSRETURN_NO;
692
693 XSRETURN_YES;
694}
695
696#if HAVE_VERSIONSORT
697
698void
699oid_lex_sort (...)
700 PROTOTYPE: @
701 PPCODE:
702{
703 // make sure SvPVX is valid
704 int i;
705 for (i = items; i--; )
706 {
707 SV *sv = ST (i);
708
709 if (SvTYPE (sv) < SVt_PV || SvTYPE (sv) == SVt_PVAV && SvTYPE (sv) == SVt_PVHV)
710 SvPV_force_nolen (sv);
711 }
712
713 qsort (&ST (0), items, sizeof (SV *), oid_lex_cmp);
714
715 EXTEND (SP, items);
716 // we cheat somewhat by not returning copies here
717 for (i = 0; i < items; ++i)
718 PUSHs (sv_2mortal (SvREFCNT_inc (ST (i))));
719}
720
721int
722_index_cmp (const char *a, const char *b)
723 PROTOTYPE: $$
724 CODE:
725 RETVAL = strverscmp (a, b);
726 OUTPUT:
727 RETVAL
728
729#endif
730

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines