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.3 by root, Wed Apr 8 13:54:42 2009 UTC vs.
Revision 1.4 by root, Thu Apr 9 04:37:05 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 ASN_BOOLEAN 0x01 7#define ASN_BOOLEAN 0x01
8#define ASN_INTEGER 0x02 8#define ASN_INTEGER32 0x02
9#define ASN_BIT_STR 0x03
10#define ASN_OCTET_STR 0x04 9#define ASN_OCTET_STRING 0x04
11#define ASN_NULL 0x05 10#define ASN_NULL 0x05
12#define ASN_OBJECT_ID 0x06 11#define ASN_OBJECT_IDENTIFIER 0x06
13#define ASN_SEQUENCE 0x10 12#define ASN_SEQUENCE 0x30
14#define ASN_SET 0x11
15
16#define ASN_UNIVERSAL 0x00 13#define ASN_IPADDRESS 0x40
17#define ASN_APPLICATION 0x40
18#define ASN_CONTEXT 0x80 14#define ASN_COUNTER32 0x41
15#define ASN_UNSIGNED32 0x42
16#define ASN_TIMETICKS 0x43
19#define ASN_PRIVATE 0xc0 17#define ASN_OPAQUE 0x44
20
21#define ASN_PRIMITIVE 0x00
22#define ASN_CONSTRUCTOR 0x20
23
24#define ASN_LONG_LEN 0x80 18#define ASN_COUNTER64 0x46
25#define ASN_EXTENSION_ID 0x1f
26#define ASN_BIT8 0x80
27 19
28#define BENCHMARK 20#define BENCHMARK
29 21
22#define MAX_OID_STRLEN 4096
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
35static SV * 29static SV *
36x_get_cv (SV *cb_sv) 30x_get_cv (SV *cb_sv)
147 } 141 }
148 142
149 return res; 143 return res;
150} 144}
151 145
146static U32
147process_integer32 (void)
148{
149 U32 length = process_length ();
150
151 if (length <= 0)
152 {
153 error ("INTEGER32 length equal to zero");
154 return 0;
155 }
156
157 U8 *data = getn (length, 0);
158
159 if (!data)
160 return 0;
161
162 if (length > 5 || (length > 4 && data [0]))
163 {
164 error ("INTEGER32 length too long");
165 return 0;
166 }
167
168 U32 res = data [0] & 0x80 ? 0xffffffff : 0;
169
170 while (length--)
171 res = (res << 8) | *data++;
172
173 return res;
174}
175
176static SV *
177process_integer32_sv (void)
178{
179 return newSViv ((I32)process_integer32 ());
180}
181
182static SV *
183process_unsigned32_sv (void)
184{
185 return newSVuv ((U32)process_integer32 ());
186}
187
188static SV *
189process_octet_string_sv (void)
190{
191 U32 length = process_length ();
192
193 U8 *data = getn (length, 0);
194 if (!data)
195 {
196 error ("OCTET STRING too long");
197 return &PL_sv_undef;
198 }
199
200 return newSVpvn (data, length);
201}
202static SV *
203process_object_identifier_sv (void)
204{
205 U32 length = process_length ();
206
207 if (length <= 0)
208 {
209 error ("OBJECT IDENTIFIER length equal to zero");
210 return &PL_sv_undef;
211 }
212
213 U8 *end = cur + length;
214 U32 w = getb ();
215
216 static char oid[MAX_OID_STRLEN];
217 char *buf = oid;
218
219 if (leading_dot)
220 *buf++ = '.';
221
222 buf += snprintf (buf, oid + sizeof (oid) - buf, "%d.%d", (int)w / 40, (int)w % 40);
223
224 while (cur < end)
225 {
226 w = getb ();
227 buf += snprintf (buf, oid + sizeof (oid) - buf, ".%u", (unsigned int)w);
228 }
229
230 return newSVpvn (oid, buf - oid);
231}
232
152static AV *av_type; 233static AV *av_type;
153 234
154MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS 235MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS
155 236
156PROTOTYPES: ENABLE 237PROTOTYPES: ENABLE
164 av_store (av_type, type, SvREFCNT_inc (x_get_cv (cv))); 245 av_store (av_type, type, SvREFCNT_inc (x_get_cv (cv)));
165 246
166void 247void
167set_msg (SV *msg_, SV *buf_) 248set_msg (SV *msg_, SV *buf_)
168 CODE: 249 CODE:
169 errflag = 0; 250 errflag = 0;
251 leading_dot = -1;
170 msg = SvREFCNT_inc (msg_); 252 msg = SvREFCNT_inc (msg_);
171 buf = SvPVbyte (buf_, len); 253 buf = SvPVbyte (buf_, len);
172 cur = buf; 254 cur = buf;
173 rem = len; 255 rem = len;
174#ifdef BENCHMARK 256#ifdef BENCHMARK
175 t1 = tstamp (); 257 t1 = tstamp ();
176#endif 258#endif
177 259
178void 260void
179clr_msg () 261clr_msg ()
180 CODE: 262 CODE:
230 CODE: 312 CODE:
231 RETVAL = process_length (); 313 RETVAL = process_length ();
232 OUTPUT: 314 OUTPUT:
233 RETVAL 315 RETVAL
234 316
235I32 317SV *
236_process_integer32 (SV *self, ...) 318_process_integer32 (SV *self, ...)
319 CODE:
320 RETVAL = process_integer32_sv ();
321 OUTPUT:
322 RETVAL
323
324SV *
325_process_counter (SV *self, ...)
237 ALIAS: 326 ALIAS:
238 _process_counter = 0
239 _process_gauge = 0 327 _process_gauge = 0
328 _process_timeticks = 0
240 CODE: 329 CODE:
241{ 330 RETVAL = process_unsigned32_sv ();
242 U32 length = process_length ();
243
244 if (length <= 0)
245 {
246 error ("INTEGER32 length equal to zero");
247 XSRETURN_UNDEF;
248 }
249
250 U8 *data = getn (length, 0);
251
252 if (!data)
253 XSRETURN_UNDEF;
254
255 if (length > 5 || (length > 4 && data [0]))
256 {
257 error ("INTEGER32 length too long");
258 XSRETURN_UNDEF;
259 }
260
261 U32 res = data [0] & 0x80 ? 0xffffffff : 0;
262
263 while (length--)
264 res = (res << 8) | *data++;
265
266 RETVAL = res;
267}
268 OUTPUT: 331 OUTPUT:
269 RETVAL 332 RETVAL
270 333
271SV * 334SV *
272_process_object_identifier (SV *self, ...) 335_process_object_identifier (SV *self, ...)
273 CODE: 336 CODE:
274{ 337 RETVAL = process_object_identifier_sv ();
275 U32 length = process_length ();
276
277 if (length <= 0)
278 {
279 error ("OBJECT IDENTIFIER length equal to zero");
280 XSRETURN_UNDEF;
281 }
282
283 U8 *end = cur + length;
284 U32 w = getb ();
285
286 //TODO: leading_dots
287
288 RETVAL = newSVpvf (".%d.%d", (int)w / 40, (int)w % 40);
289
290 while (cur < end)
291 {
292 w = getb ();
293 sv_catpvf (RETVAL, ".%u", (unsigned int)w);
294 }
295}
296 OUTPUT: 338 OUTPUT:
297 RETVAL 339 RETVAL
298 340
299SV * 341SV *
300_process_octet_string (SV *self, ...) 342_process_octet_string (SV *self, ...)
301 ALIAS: 343 ALIAS:
302 _process_opaque = 0 344 _process_opaque = 0
303 CODE: 345 CODE:
304{ 346 RETVAL = process_octet_string_sv ();
305 U32 length = process_length ();
306
307 U8 *data = getn (length, 0);
308 if (!data)
309 {
310 error ("OCTET STRING too long");
311 XSRETURN_UNDEF;
312 }
313
314 RETVAL = newSVpvn (data, length);
315}
316 OUTPUT: 347 OUTPUT:
317 RETVAL 348 RETVAL
318 349
319SV * 350SV *
320_process_ipaddress (SV *self, ...) 351_process_ipaddress (SV *self, ...)
353 } 384 }
354 385
355 if (found) 386 if (found)
356 sv_setiv (found, type); 387 sv_setiv (found, type);
357 388
389 //TODO: switch based on type, to avoid calling overhead
358 SV *res; 390 SV *res;
359 391
392 switch (type)
360 { 393 {
394 case ASN_OBJECT_IDENTIFIER:
395 res = sv_2mortal (process_object_identifier_sv ());
396 break;
397
398 case ASN_INTEGER32:
399 res = sv_2mortal (process_integer32_sv ());
400 break;
401
402 case ASN_UNSIGNED32:
403 case ASN_COUNTER32:
404 case ASN_TIMETICKS:
405 res = sv_2mortal (process_unsigned32_sv ());
406 break;
407
408 case ASN_SEQUENCE:
409 res = sv_2mortal (newSVuv (process_length ()));
410 break;
411
412 case ASN_OCTET_STRING:
413 case ASN_OPAQUE:
414 res = sv_2mortal (process_octet_string_sv ());
415 break;
416
417 default:
418 {
361 dSP; 419 dSP;
362 PUSHMARK (SP); 420 PUSHMARK (SP);
363 EXTEND (SP, 2); 421 EXTEND (SP, 2);
364 PUSHs (self); 422 PUSHs (self);
365 PUSHs (expected); 423 PUSHs (expected);
366 PUTBACK; 424 PUTBACK;
367 int count = call_sv (AvARRAY (av_type)[type], G_SCALAR); 425 int count = call_sv (AvARRAY (av_type)[type], G_SCALAR);
368 SPAGAIN; 426 SPAGAIN;
369 res = count ? TOPs : &PL_sv_undef; 427 res = count ? TOPs : &PL_sv_undef;
428 }
429 }
430
431 XPUSHs (errflag ? &PL_sv_undef : res);
432}
433
434#if 0
435
436MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::PDU
437
438SV *
439_process_var_bind_list (SV *self)
440 CODE:
441{
442 # VarBindList::=SEQUENCE
443 if (!defined($value = $this->process(SEQUENCE))) {
444 return $this->_error;
370 } 445 }
371 446
372 XPUSHs (res); 447 # Using the length of the VarBindList SEQUENCE,
448 # calculate the end index.
449
450 my $end = $this->index + $value;
451
452 $this->{_var_bind_list} = {};
453 $this->{_var_bind_names} = [];
454 $this->{_var_bind_types} = {};
455
456 my ($oid, $type);
457
458 while ($this->index < $end) {
459
460 # VarBind::=SEQUENCE
461 if (!defined($this->process(SEQUENCE))) {
462 return $this->_error;
463 }
464 # name::=ObjectName
465 if (!defined($oid = $this->process(OBJECT_IDENTIFIER))) {
466 return $this->_error;
467 }
468 # value::=ObjectSyntax
469 if (!defined($value = $this->process(undef, $type))) {
470 return $this->_error;
471 }
472
473 # Create a hash consisting of the OBJECT IDENTIFIER as a
474 # key and the ObjectSyntax as the value. If there is a
475 # duplicate OBJECT IDENTIFIER in the VarBindList, we pad
476 # that OBJECT IDENTIFIER with spaces to make a unique
477 # key in the hash.
478
479 while (exists($this->{_var_bind_list}->{$oid})) {
480 $oid .= ' '; # Pad with spaces
481 }
482
483 DEBUG_INFO('{ %s => %s: %s }', $oid, asn1_itoa($type), $value);
484 $this->{_var_bind_list}->{$oid} = $value;
485 $this->{_var_bind_types}->{$oid} = $type;
486
487 # Create an array with the ObjectName OBJECT IDENTIFIERs
488 # so that the order in which the VarBinds where encoded
489 # in the PDU can be retrieved later.
490
491 push(@{$this->{_var_bind_names}}, $oid);
492
493 }
494
495 # Return an error based on the contents of the VarBindList
496 # if we received a Report-PDU.
497
498 return $this->_report_pdu_error if ($this->{_pdu_type} == REPORT);
499
500 # Return the var_bind_list hash
501 $this->{_var_bind_list};
373} 502}
374 503
504#endif
505

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines