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.1 by root, Wed Apr 8 10:30:46 2009 UTC vs.
Revision 1.8 by root, Thu Apr 9 10:08:25 2009 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 BENCHMARK
8
7#define ASN_BOOLEAN 0x01 9#define ASN_BOOLEAN 0x01
8#define ASN_INTEGER 0x02 10#define ASN_INTEGER32 0x02
9#define ASN_BIT_STR 0x03
10#define ASN_OCTET_STR 0x04 11#define ASN_OCTET_STRING 0x04
11#define ASN_NULL 0x05 12#define ASN_NULL 0x05
12#define ASN_OBJECT_ID 0x06 13#define ASN_OBJECT_IDENTIFIER 0x06
13#define ASN_SEQUENCE 0x10 14#define ASN_SEQUENCE 0x30
14#define ASN_SET 0x11
15
16#define ASN_UNIVERSAL 0x00 15#define ASN_IPADDRESS 0x40
17#define ASN_APPLICATION 0x40
18#define ASN_CONTEXT 0x80 16#define ASN_COUNTER32 0x41
17#define ASN_UNSIGNED32 0x42
18#define ASN_TIMETICKS 0x43
19#define ASN_PRIVATE 0xc0 19#define ASN_OPAQUE 0x44
20
21#define ASN_PRIMITIVE 0x00
22#define ASN_CONSTRUCTOR 0x20
23
24#define ASN_LONG_LEN 0x80 20#define ASN_COUNTER64 0x46
25#define ASN_EXTENSION_ID 0x1f
26#define ASN_BIT8 0x80
27 21
28#define BENCHMARK 22#define MAX_OID_STRLEN 4096
29 23
30static SV *msg; 24static SV *msg;
31static int errflag; 25static int errflag, leading_dot;
32static U8 *buf, *cur; 26static U8 *buf, *cur;
33static STRLEN len, rem; 27static STRLEN len, rem;
34 28
29static SV *
30x_get_cv (SV *cb_sv)
31{
32 HV *st;
33 GV *gvp;
34 CV *cv = sv_2cv (cb_sv, &st, &gvp, 0);
35
36 if (!cv)
37 croak ("CODE reference expected");
38
39 return (SV *)cv;
40}
41
35static void 42static void
36error (const char *msg) 43error (const char *errmsg)
37{ 44{
38 errflag = 1; 45 errflag = 1;
39 46
40 printf ("<<<%s>>>\n", msg);//D 47 dSP;
48 PUSHMARK (SP);
49 EXTEND (SP, 2);
50 PUSHs (msg);
51 PUSHs (sv_2mortal (newSVpv (errmsg, 0)));
52 PUTBACK;
53 call_method ("_error", G_VOID | G_DISCARD);
41} 54}
42 55
43static int 56static int
44need (int count) 57need (int count)
45{ 58{
134 } 147 }
135 148
136 return res; 149 return res;
137} 150}
138 151
152static U32
153process_integer32 (void)
154{
155 U32 length = process_length ();
156
157 if (length <= 0)
158 {
159 error ("INTEGER32 length equal to zero");
160 return 0;
161 }
162
163 U8 *data = getn (length, 0);
164
165 if (!data)
166 return 0;
167
168 if (length > 5 || (length > 4 && data [0]))
169 {
170 error ("INTEGER32 length too long");
171 return 0;
172 }
173
174 U32 res = data [0] & 0x80 ? 0xffffffff : 0;
175
176 while (length--)
177 res = (res << 8) | *data++;
178
179 return res;
180}
181
182static SV *
183process_integer32_sv (void)
184{
185 return newSViv ((I32)process_integer32 ());
186}
187
188static SV *
189process_unsigned32_sv (void)
190{
191 return newSVuv ((U32)process_integer32 ());
192}
193
194#if IVSIZE >= 8
195
196static U64TYPE
197process_integer64 (void)
198{
199 U32 length = process_length ();
200
201 if (length <= 0)
202 {
203 error ("INTEGER64 length equal to zero");
204 return 0;
205 }
206
207 U8 *data = getn (length, 0);
208
209 if (!data)
210 return 0;
211
212 if (length > 9 || (length > 8 && data [0]))
213 {
214 error ("INTEGER64 length too long");
215 return 0;
216 }
217
218 U64TYPE res = data [0] & 0x80 ? 0xffffffffffffffff : 0;
219
220 while (length--)
221 res = (res << 8) | *data++;
222
223 return res;
224}
225
226static SV *
227process_integer64_sv (void)
228{
229 return newSViv ((I64TYPE)process_integer64 ());
230}
231
232static SV *
233process_unsigned64_sv (void)
234{
235 return newSVuv ((U64TYPE)process_integer64 ());
236}
237
238#endif
239
240static SV *
241process_octet_string_sv (void)
242{
243 U32 length = process_length ();
244
245 U8 *data = getn (length, 0);
246 if (!data)
247 {
248 error ("OCTET STRING too long");
249 return &PL_sv_undef;
250 }
251
252 return newSVpvn (data, length);
253}
254
255static char *
256write_uv (char *buf, U32 u)
257{
258 // the one-digit case is absolutely predominant
259 if (u < 10)
260 *buf++ = u + '0';
261 else
262 buf += sprintf (buf, "%u", (unsigned int)u);
263
264 return buf;
265}
266
267static SV *
268process_object_identifier_sv (void)
269{
270 U32 length = process_length ();
271
272 if (length <= 0)
273 {
274 error ("OBJECT IDENTIFIER length equal to zero");
275 return &PL_sv_undef;
276 }
277
278 U8 *end = cur + length;
279 U32 w = getb ();
280
281 static char oid[MAX_OID_STRLEN]; // must be static
282 char *app = oid;
283
284 *app = '.'; app += ! ! leading_dot;
285 app = write_uv (app, (U8)w / 40);
286 *app++ = '.';
287 app = write_uv (app, (U8)w % 40);
288
289 // we assume an oid component is never > 64 bytes
290 while (cur < end && oid + sizeof (oid) - app > 64)
291 {
292 w = getb ();
293 *app++ = '.';
294 app = write_uv (app, w);
295 }
296
297 return newSVpvn (oid, app - oid);
298}
299
300static AV *av_type;
301
302static SV *
303process_sv (int *found)
304{
305 int type = get8 ();
306
307 *found = type;
308
309 SV *res;
310
311 switch (type)
312 {
313 case ASN_OBJECT_IDENTIFIER:
314 res = process_object_identifier_sv ();
315 break;
316
317 case ASN_INTEGER32:
318 res = process_integer32_sv ();
319 break;
320
321 case ASN_UNSIGNED32:
322 case ASN_COUNTER32:
323 case ASN_TIMETICKS:
324 res = process_unsigned32_sv ();
325 break;
326
327 case ASN_SEQUENCE:
328 res = newSVuv (process_length ());
329 break;
330
331 case ASN_OCTET_STRING:
332 case ASN_OPAQUE:
333 res = process_octet_string_sv ();
334 break;
335
336 default:
337 {
338 if (type > AvFILLp (av_type) || !SvTYPE (AvARRAY (av_type)[type]) == SVt_PVCV)
339 {
340 error ("Unknown ASN.1 type");
341 return &PL_sv_undef;
342 }
343
344 dSP;
345 PUSHMARK (SP);
346 EXTEND (SP, 2);
347 PUSHs (msg);
348 PUSHs (sv_2mortal (newSViv (type)));
349 PUTBACK;
350 int count = call_sv (AvARRAY (av_type)[type], G_SCALAR);
351 SPAGAIN;
352 res = count ? SvREFCNT_inc (TOPs) : &PL_sv_undef;
353 }
354 }
355
356 return errflag ? &PL_sv_undef : res;
357}
358
139MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS 359MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS
360
361PROTOTYPES: ENABLE
362
363BOOT:
364 av_type = newAV ();
365
366void
367set_type (int type, SV *cv)
368 CODE:
369 av_store (av_type, type, SvREFCNT_inc (x_get_cv (cv)));
140 370
141void 371void
142set_msg (SV *msg_, SV *buf_) 372set_msg (SV *msg_, SV *buf_)
143 CODE: 373 CODE:
374{
375 if (msg)
376 croak ("recursive invocation of Net::SNMP::XS parser is not supported");
377
144 errflag = 0; 378 errflag = 0;
379 leading_dot = -1;
145 msg = SvREFCNT_inc (msg_); 380 msg = SvREFCNT_inc (msg_);
146 buf = SvPVbyte (buf_, len); 381 buf = SvPVbyte (buf_, len);
147 cur = buf; 382 cur = buf;
148 rem = len; 383 rem = len;
149 #ifdef BENCHMARK 384#ifdef BENCHMARK
150 t1 = tstamp (); 385 t1 = tstamp ();
151 #endif 386#endif
387}
152 388
153void 389void
154clr_msg () 390clr_msg ()
155 CODE: 391 CODE:
156 SvREFCNT_dec (msg); 392 SvREFCNT_dec (msg); msg = 0;
157 buf = cur = ""; 393 buf = cur = (U8 *)"";
158 len = rem = 0; 394 len = rem = 0;
159 #ifdef BENCHMARK 395#ifdef BENCHMARK
160 printf ("%f\n", tstamp () - t1);//D 396 printf ("%f\n", tstamp () - t1);//D
161 #endif 397#endif
162 398
163MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message 399MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message
164 400
165void 401void
166_buffer_get (SV *self, int count = -1) 402_buffer_get (SV *self, int count = -1)
199 RETVAL 435 RETVAL
200 436
201U32 437U32
202_process_length (SV *self, ...) 438_process_length (SV *self, ...)
203 ALIAS: 439 ALIAS:
204 _process_sequence = 1 440 _process_sequence = 0
205 CODE: 441 CODE:
206 RETVAL = process_length (); 442 RETVAL = process_length ();
207 OUTPUT: 443 OUTPUT:
208 RETVAL 444 RETVAL
209 445
210I32 446SV *
211_process_integer32 (SV *self, ...) 447_process_integer32 (SV *self, ...)
448 CODE:
449 RETVAL = process_integer32_sv ();
450 OUTPUT:
451 RETVAL
452
453SV *
454_process_counter (SV *self, ...)
212 ALIAS: 455 ALIAS:
213 _process_counter = 0
214 _process_gauge = 0 456 _process_gauge = 0
457 _process_timeticks = 0
215 CODE: 458 CODE:
216{ 459 RETVAL = process_unsigned32_sv ();
217 U32 length = process_length (); 460 OUTPUT:
218
219 if (length <= 0)
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; 461 RETVAL
242} 462
463#if IVSIZE >= 8
464
465SV *
466_process_counter64 (SV *self, ...)
467 CODE:
468 RETVAL = process_unsigned64_sv ();
243 OUTPUT: 469 OUTPUT:
244 RETVAL 470 RETVAL
471
472#endif
245 473
246SV * 474SV *
247_process_object_identifier (SV *self, ...) 475_process_object_identifier (SV *self, ...)
248 CODE: 476 CODE:
249{ 477 RETVAL = process_object_identifier_sv ();
250 U32 length = process_length ();
251
252 if (length <= 0)
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: 478 OUTPUT:
272 RETVAL 479 RETVAL
273 480
274SV * 481SV *
275_process_octet_string (SV *self, ...) 482_process_octet_string (SV *self, ...)
276 ALIAS: 483 ALIAS:
277 _process_opaque = 0 484 _process_opaque = 0
278 CODE: 485 CODE:
279{ 486 RETVAL = process_octet_string_sv ();
280 U32 length = process_length ();
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: 487 OUTPUT:
292 RETVAL 488 RETVAL
293 489
294SV * 490SV *
295_process_ipaddress (SV *self, ...) 491_process_ipaddress (SV *self, ...)
306 RETVAL = newSVpvf ("%d.%d.%d.%d", data [0], data [1], data [2], data [3]); 502 RETVAL = newSVpvf ("%d.%d.%d.%d", data [0], data [1], data [2], data [3]);
307} 503}
308 OUTPUT: 504 OUTPUT:
309 RETVAL 505 RETVAL
310 506
507SV *
508process (SV *self, SV *expected = &PL_sv_undef, SV *found = 0)
509 CODE:
510{
511 int type;
512
513 RETVAL = process_sv (&type);
514
515 if (found)
516 sv_setiv (found, type);
517
518 if (SvOK (expected) && type != SvIV (expected))
519 error ("Expected a different type than found");
520}
521 OUTPUT:
522 RETVAL
523
524MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::PDU
525
526SV *
527_process_var_bind_list (SV *self)
528 CODE:
529{
530 if (get8 () != ASN_SEQUENCE)
531 error ("SEQUENCE expected at beginning of VarBindList");
532 int seqlen = process_length ();
533 U8 *end = cur + seqlen;
534
535 HV *list = newHV ();
536 AV *names = newAV ();
537 HV *types = newHV ();
538
539 hv_store ((HV *)SvRV (self), "_var_bind_list" , sizeof ("_var_bind_list" ) - 1, newRV_noinc ((SV *)list ), 0);
540 hv_store ((HV *)SvRV (self), "_var_bind_names", sizeof ("_var_bind_names") - 1, newRV_noinc ((SV *)names), 0);
541 hv_store ((HV *)SvRV (self), "_var_bind_types", sizeof ("_var_bind_types") - 1, newRV_noinc ((SV *)types), 0);
542
543 while (cur < end && !errflag)
544 {
545 // SEQUENCE ObjectName ObjectSyntax
546 if (get8 () != ASN_SEQUENCE)
547 error ("SEQUENCE expected at beginning of VarBind");
548 process_length ();
549
550 if (get8 () != ASN_OBJECT_IDENTIFIER)
551 error ("OBJECT IDENTIFIER expected at beginning of VarBind");
552 int type, oidlen;
553 SV *oid = process_object_identifier_sv ();
554 SV *val = process_sv (&type);
555
556 hv_store_ent (types, oid, newSViv (type), 0);
557 hv_store_ent (list , oid, val, 0);
558 av_push (names, oid);
559 }
560
561 //return $this->_report_pdu_error if ($this->{_pdu_type} == REPORT);
562
563 RETVAL = newRV_inc ((SV *)list);
564}
565 OUTPUT:
566 RETVAL
567
568

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines