1 /* -*- C -*- */
2
3 #include "EXTERN.h"
4 #include "perl.h"
5 #include "XSUB.h"
6 #include <netdb.h>
7 #include <sys/socket.h>
8
9 #include <net-snmp/net-snmp-config.h>
10 #include <net-snmp/net-snmp-includes.h>
11 #include <net-snmp/agent/net-snmp-agent-includes.h>
12
13 #ifndef sv_undef
14 #define sv_undef PL_sv_undef
15 #endif
16
17 typedef netsnmp_handler_registration *NetSNMP__agent__netsnmp_handler_registration;
18
19 /*
20 * needs to be in sync with the definitions in snmplib/snmpUDPDomain.c
21 * and snmplib/snmpTCPDomain.c
22 */
23 typedef netsnmp_indexed_addr_pair netsnmp_udp_addr_pair;
24
25 typedef struct handler_cb_data_s {
26 SV *perl_cb;
27 } handler_cb_data;
28
29 typedef struct netsnmp_oid_s {
30 oid *name;
31 size_t len;
32 oid namebuf[ MAX_OID_LEN ];
33 } netsnmp_oid;
34
35 #define TEST_CONSTANT(value, name, C) \
36 if (strEQ(name, #C)) { \
37 *value = C; \
38 return 0; \
39 }
40
constant_MODE_G(double * value,const char * name,const int len)41 static int constant_MODE_G(double *value, const char *name, const int len)
42 {
43 switch (len >= 8 ? name[8] : -1) {
44 case '\0':
45 TEST_CONSTANT(value, name, MODE_GET);
46 break;
47 case 'B':
48 TEST_CONSTANT(value, name, MODE_GETBULK);
49 break;
50 case 'N':
51 TEST_CONSTANT(value, name, MODE_GETNEXT);
52 break;
53 }
54 return EINVAL;
55 }
56
constant_MODE_SET_R(double * value,const char * name,const int len)57 static int constant_MODE_SET_R(double *value, const char *name, const int len)
58 {
59 switch (len >= 16 ? name[16] : -1) {
60 #ifndef NETSNMP_NO_WRITE_SUPPORT
61 case '1':
62 TEST_CONSTANT(value, name, MODE_SET_RESERVE1);
63 break;
64 case '2':
65 TEST_CONSTANT(value, name, MODE_SET_RESERVE2);
66 break;
67 #endif /* NETSNMP_NO_WRITE_SUPPORT */
68 }
69 return EINVAL;
70 }
71
constant_SNMP_ERR(double * value,char * name,int len)72 static int constant_SNMP_ERR(double *value, char *name, int len)
73 {
74 switch (len >= 9 ? name[9] : -1) {
75 case 'A':
76 TEST_CONSTANT(value, name, SNMP_ERR_AUTHORIZATIONERROR);
77 break;
78 case 'B':
79 TEST_CONSTANT(value, name, SNMP_ERR_BADVALUE);
80 break;
81 case 'C':
82 TEST_CONSTANT(value, name, SNMP_ERR_COMMITFAILED);
83 break;
84 case 'G':
85 TEST_CONSTANT(value, name, SNMP_ERR_GENERR);
86 break;
87 case 'I':
88 TEST_CONSTANT(value, name, SNMP_ERR_INCONSISTENTVALUE);
89 break;
90 case 'N':
91 TEST_CONSTANT(value, name, SNMP_ERR_NOACCESS);
92 TEST_CONSTANT(value, name, SNMP_ERR_NOCREATION);
93 TEST_CONSTANT(value, name, SNMP_ERR_NOERROR);
94 TEST_CONSTANT(value, name, SNMP_ERR_NOSUCHNAME);
95 TEST_CONSTANT(value, name, SNMP_ERR_NOTWRITABLE);
96 break;
97 case 'R':
98 TEST_CONSTANT(value, name, SNMP_ERR_READONLY);
99 TEST_CONSTANT(value, name, SNMP_ERR_RESOURCEUNAVAILABLE);
100 break;
101 case 'T':
102 TEST_CONSTANT(value, name, SNMP_ERR_TOOBIG);
103 break;
104 case 'U':
105 TEST_CONSTANT(value, name, SNMP_ERR_UNDOFAILED);
106 break;
107 case 'W':
108 TEST_CONSTANT(value, name, SNMP_ERR_WRONGENCODING);
109 TEST_CONSTANT(value, name, SNMP_ERR_WRONGLENGTH);
110 TEST_CONSTANT(value, name, SNMP_ERR_WRONGTYPE);
111 TEST_CONSTANT(value, name, SNMP_ERR_WRONGVALUE);
112 break;
113 }
114 return EINVAL;
115 }
116
constant_MODE_S(double * value,char * name,int len)117 static int constant_MODE_S(double *value, char *name, int len)
118 {
119 if (!strnEQ(name + 6, "ET_", 3))
120 return EINVAL;
121
122 switch (len >= 9 ? name[9] : -1) {
123 #ifndef NETSNMP_NO_WRITE_SUPPORT
124 case 'A':
125 TEST_CONSTANT(value, name, MODE_SET_ACTION);
126 break;
127 case 'B':
128 TEST_CONSTANT(value, name, MODE_SET_BEGIN);
129 break;
130 case 'C':
131 TEST_CONSTANT(value, name, MODE_SET_COMMIT);
132 break;
133 case 'F':
134 TEST_CONSTANT(value, name, MODE_SET_FREE);
135 break;
136 case 'U':
137 TEST_CONSTANT(value, name, MODE_SET_UNDO);
138 break;
139 #endif /* NETSNMP_NO_WRITE_SUPPORT */
140 case 'R':
141 return constant_MODE_SET_R(value, name, len);
142 }
143 return EINVAL;
144 }
145
constant(double * value,char * name,int len)146 static int constant(double *value, char *name, int len)
147 {
148 switch (len >= 5 ? name[5] : -1) {
149 case 'G':
150 if (strnEQ(name + 0,"MODE_", 5))
151 return constant_MODE_G(value, name, len);
152 break;
153 case 'S':
154 if (strnEQ(name + 0,"MODE_", 5))
155 return constant_MODE_S(value, name, len);
156 break;
157 case 'E':
158 if (strnEQ(name + 0,"SNMP_ERR_", 9))
159 return constant_SNMP_ERR(value, name, len);
160 break;
161 }
162 return EINVAL;
163 }
164
165 int
handler_wrapper(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * reqinfo,netsnmp_request_info * requests)166 handler_wrapper(netsnmp_mib_handler *handler,
167 netsnmp_handler_registration *reginfo,
168 netsnmp_agent_request_info *reqinfo,
169 netsnmp_request_info *requests)
170 {
171 handler_cb_data *cb_data = (handler_cb_data *) handler->myvoid;
172 SV *cb;
173
174 if (cb_data && (cb = cb_data->perl_cb)) {
175 SV *arg;
176 SV *rarg;
177 dSP;
178 ENTER;
179 SAVETMPS;
180 PUSHMARK(sp);
181 rarg = newSViv(0);
182 arg = newSVrv(rarg, "NetSNMP::agent::netsnmp_mib_handler");
183 sv_setiv(arg, (IV) handler);
184 XPUSHs(sv_2mortal(rarg));
185 rarg = newSViv(0);
186 arg = newSVrv(rarg, "NetSNMP::agent::netsnmp_handler_registrationPtr");
187 sv_setiv(arg, (IV) reginfo);
188 XPUSHs(sv_2mortal(rarg));
189 rarg = newSViv(0);
190 arg = newSVrv(rarg, "NetSNMP::agent::netsnmp_agent_request_info");
191 sv_setiv(arg, (IV) reqinfo);
192 XPUSHs(sv_2mortal(rarg));
193 rarg = newSViv(0);
194 arg = newSVrv(rarg, "NetSNMP::agent::netsnmp_request_infoPtr");
195 sv_setiv(arg, (IV) requests);
196 XPUSHs(sv_2mortal(rarg));
197 PUTBACK;
198 if (SvTYPE(cb) == SVt_PVCV) {
199 perl_call_sv(cb, G_DISCARD);
200
201 } else if (SvROK(cb) && SvTYPE(SvRV(cb)) == SVt_PVCV) {
202 perl_call_sv(SvRV(cb), G_DISCARD);
203 }
204 SPAGAIN;
205 PUTBACK;
206 FREETMPS;
207 LEAVE;
208 }
209 return SNMP_ERR_NOERROR;
210 }
211
212 MODULE = NetSNMP::agent PACKAGE = NetSNMP::agent
213
214 void
215 constant(sv)
216 PREINIT:
217 STRLEN len;
218 INPUT:
219 SV * sv
220 char * s = SvPV(sv, len);
221 INIT:
222 int status;
223 double value;
224 PPCODE:
225 value = 0;
226 status = constant(&value, s, len);
227 XPUSHs(sv_2mortal(newSVuv(status)));
228 XPUSHs(sv_2mortal(newSVnv(value)));
229
230 int
231 __agent_check_and_process(block = 1)
232 int block;
233 CODE:
234 RETVAL = agent_check_and_process(block);
235 OUTPUT:
236 RETVAL
237
238 int
239 _uptime()
240 CODE:
241 RETVAL = netsnmp_get_agent_uptime();
242 OUTPUT:
243 RETVAL
244
245 void
init_mib()246 init_mib()
247 CODE:
248 {
249 netsnmp_init_mib();
250 }
251
252 int
253 init_agent(name)
254 const char *name;
255 CODE:
256 SOCK_STARTUP;
257 RETVAL = init_agent(name);
258 OUTPUT:
259 RETVAL
260
261 void
262 init_snmp(name)
263 const char *name;
264
265 int
266 init_master_agent()
267
268 void
269 snmp_enable_stderrlog()
270
271 MODULE = NetSNMP::agent PACKAGE = NetSNMP::agent PREFIX = na_
272
273 void
274 na_shutdown(me)
275 SV *me;
276 CODE:
277 {
278 if (0)
279 printf("me = %p\n", me);
280 snmp_shutdown("perl");
281 }
282
283 void
284 na_errlog(me,value)
285 SV *me;
286 SV *value;
287 PREINIT:
288 STRLEN stringlen;
289 char * stringptr;
290 CODE:
291 {
292 if (0)
293 printf("me = %p\n", me);
294 stringptr = SvPV(value, stringlen);
295 snmp_log(LOG_ERR, "%s", stringptr );
296 }
297
298
299
300 MODULE = NetSNMP::agent PACKAGE = NetSNMP::agent::netsnmp_handler_registration PREFIX = nsahr_
301
302 NetSNMP::agent::netsnmp_handler_registration
303 nsahr_new(name, regoid, perlcallback)
304 char *name;
305 char *regoid;
306 SV *perlcallback;
307 PREINIT:
308 oid myoid[MAX_OID_LEN];
309 size_t myoid_len = MAX_OID_LEN;
310 handler_cb_data *cb_data;
311 int gotit=1;
312 CODE:
313 if (!snmp_parse_oid(regoid, myoid, &myoid_len)) {
314 if (!read_objid(regoid, myoid, &myoid_len)) {
315 snmp_log(LOG_ERR, "couldn't parse %s (reg name: %s)\n",
316 regoid, name);
317 RETVAL = NULL;
318 gotit = 0;
319 }
320 }
321 if (gotit) {
322 cb_data = (handler_cb_data *) malloc(sizeof(handler_cb_data));
323 RETVAL = netsnmp_create_handler_registration(name, handler_wrapper,
324 myoid, myoid_len,
325 HANDLER_CAN_RWRITE);
326 cb_data->perl_cb = newSVsv(perlcallback);
327 RETVAL->handler->myvoid = cb_data;
328 }
329 OUTPUT:
330 RETVAL
331
332 void
nsahr_DESTROY(reginfo)333 nsahr_DESTROY(reginfo)
334 netsnmp_handler_registration *reginfo
335 PREINIT:
336 handler_cb_data *cb_data;
337 CODE:
338 if (reginfo && reginfo->handler && reginfo->handler->myvoid) {
339 cb_data = (handler_cb_data *) (reginfo->handler->myvoid);
340 SvREFCNT_dec(cb_data->perl_cb);
341 free(cb_data);
342 }
343 netsnmp_handler_registration_free(reginfo);
344
345 int
346 nsahr_register(me)
347 SV *me;
348 PREINIT:
349 netsnmp_handler_registration *reginfo;
350 handler_cb_data *cb_data = NULL;
351 CODE:
352 {
353 reginfo = (netsnmp_handler_registration *) SvIV(SvRV(me));
354 if (reginfo && reginfo->handler && reginfo->handler->myvoid)
355 cb_data = (handler_cb_data *) (reginfo->handler->myvoid);
356 RETVAL = netsnmp_register_handler(reginfo);
357 if (!RETVAL) {
358 /* the agent now has a "reference" to this reg pointer */
359 SvREFCNT_inc(me);
360 } else {
361 /*
362 * The reginfo was freed by netsnmp_register_handler,
363 * don't touch it in nsahr_DESTROY!
364 */
365 sv_setiv(SvRV(me), 0);
366 if (cb_data) {
367 /* And just free the callback. */
368 SvREFCNT_dec(cb_data->perl_cb);
369 free(cb_data);
370 }
371 }
372 }
373 OUTPUT:
374 RETVAL
375
376
377 MODULE = NetSNMP::agent PACKAGE = NetSNMP::agent::netsnmp_handler_registrationPtr PREFIX = nsahr_
378
379 void
380 nsahr_getRootOID(me)
381 SV *me;
382 PREINIT:
383 int i;
384 netsnmp_oid *o;
385 netsnmp_handler_registration *reginfo;
386 SV *arg, *rarg;
387 PPCODE:
388 {
389 dSP;
390 PUSHMARK(SP);
391 reginfo = (netsnmp_handler_registration *) SvIV(SvRV(me));
392
393 o = malloc(sizeof(netsnmp_oid));
394 o->name = o->namebuf;
395 o->len = reginfo->rootoid_len;
396 memcpy(o->name, reginfo->rootoid,
397 reginfo->rootoid_len * sizeof(oid));
398
399 rarg = newSViv((int) 0);
400 arg = newSVrv(rarg, "netsnmp_oidPtr");
401 sv_setiv(arg, (IV) o);
402
403 XPUSHs(sv_2mortal(rarg));
404
405 PUTBACK;
406 i = perl_call_pv("NetSNMP::OID::newwithptr", G_SCALAR);
407 SPAGAIN;
408 if (i != 1) {
409 snmp_log(LOG_ERR, "unhandled OID error.\n");
410 /* ack XXX */
411 }
412 ST(0) = POPs;
413 XSRETURN(1);
414 }
415
416 MODULE = NetSNMP::agent PACKAGE = NetSNMP::agent::netsnmp_request_infoPtr PREFIX = nari_
417
418 void
419 getOID(me)
420 SV *me;
421 PREINIT:
422 int i;
423 netsnmp_oid *o;
424 netsnmp_request_info *request;
425 SV *arg, *rarg;
426 PPCODE:
427 {
428 dSP;
429 PUSHMARK(SP);
430 request = (netsnmp_request_info *) SvIV(SvRV(me));
431
432 o = malloc(sizeof(netsnmp_oid));
433 o->name = o->namebuf;
434 o->len = request->requestvb->name_length;
435 memcpy(o->name, request->requestvb->name,
436 request->requestvb->name_length * sizeof(oid));
437
438 rarg = newSViv((int) 0);
439 arg = newSVrv(rarg, "netsnmp_oidPtr");
440 sv_setiv(arg, (IV) o);
441
442 XPUSHs(sv_2mortal(rarg));
443
444 PUTBACK;
445 i = perl_call_pv("NetSNMP::OID::newwithptr", G_SCALAR);
446 SPAGAIN;
447 if (i != 1) {
448 snmp_log(LOG_ERR, "unhandled OID error.\n");
449 /* ack XXX */
450 }
451 ST(0) = POPs;
452 XSRETURN(1);
453 }
454
455 netsnmp_oid *
456 nari_getOIDptr(me)
457 SV *me;
458 PREINIT:
459 netsnmp_request_info *request;
460 CODE:
461 request = (netsnmp_request_info *) SvIV(SvRV(me));
462 RETVAL = malloc(sizeof(netsnmp_oid));
463 RETVAL->name = RETVAL->namebuf;
464 RETVAL->len = request->requestvb->name_length;
465 memcpy(RETVAL->name, request->requestvb->name,
466 request->requestvb->name_length * sizeof(oid));
467 OUTPUT:
468 RETVAL
469
470 int
471 nari_getType(me)
472 SV *me;
473 PREINIT:
474 netsnmp_request_info *request;
475 CODE:
476 request = (netsnmp_request_info *) SvIV(SvRV(me));
477
478 RETVAL = request->requestvb->type ;
479 OUTPUT:
480 RETVAL
481
482 void
483 nari_setType(me, newvalue)
484 SV *me;
485 int newvalue;
486 PREINIT:
487 netsnmp_request_info *request;
488 CODE:
489 request = (netsnmp_request_info *) SvIV(SvRV(me));
490 request->requestvb->type=newvalue;
491
492 SV *
493 nari_getValue(me)
494 SV *me;
495 PREINIT:
496 char *outbuf = NULL;
497 size_t ob_len = 0, oo_len = 0;
498 netsnmp_request_info *request;
499 CODE:
500 request = (netsnmp_request_info *) SvIV(SvRV(me));
501 sprint_realloc_by_type((u_char **) &outbuf, &ob_len, &oo_len, 1,
502 request->requestvb, 0, 0, 0);
503 RETVAL = newSVpv(outbuf, 0);
504 netsnmp_free(outbuf);
505 OUTPUT:
506 RETVAL
507
508 int
509 nari_getDelegated(me)
510 SV *me;
511 PREINIT:
512 netsnmp_request_info *request;
513 CODE:
514 request = (netsnmp_request_info *) SvIV(SvRV(me));
515 RETVAL = request->delegated;
516 OUTPUT:
517 RETVAL
518
519 void
520 nari_setDelegated(me, newdelegated)
521 SV *me;
522 int newdelegated;
523 PREINIT:
524 netsnmp_request_info *request;
525 CODE:
526 request = (netsnmp_request_info *) SvIV(SvRV(me));
527 request->delegated = newdelegated;
528
529 int
530 nari_getProcessed(me)
531 SV *me;
532 PREINIT:
533 netsnmp_request_info *request;
534 CODE:
535 request = (netsnmp_request_info *) SvIV(SvRV(me));
536 RETVAL = request->processed;
537 OUTPUT:
538 RETVAL
539
540 void
541 nari_setProcessed(me, newprocessed)
542 SV *me;
543 int newprocessed;
544 PREINIT:
545 netsnmp_request_info *request;
546 CODE:
547 request = (netsnmp_request_info *) SvIV(SvRV(me));
548 request->processed = newprocessed;
549
550 int
551 nari_getStatus(me)
552 SV *me;
553 PREINIT:
554 netsnmp_request_info *request;
555 CODE:
556 request = (netsnmp_request_info *) SvIV(SvRV(me));
557 RETVAL = request->status;
558 OUTPUT:
559 RETVAL
560
561 void
562 nari_setStatus(me, newstatus)
563 SV *me;
564 int newstatus;
565 PREINIT:
566 netsnmp_request_info *request;
567 CODE:
568 request = (netsnmp_request_info *) SvIV(SvRV(me));
569 request->status = newstatus;
570
571 int
572 nari_getRepeat(me)
573 SV *me;
574 PREINIT:
575 netsnmp_request_info *request;
576 CODE:
577 request = (netsnmp_request_info *) SvIV(SvRV(me));
578 RETVAL = request->repeat;
579 OUTPUT:
580 RETVAL
581
582 void
583 nari_setRepeat(me, newrepeat)
584 SV *me;
585 int newrepeat;
586 PREINIT:
587 netsnmp_request_info *request;
588 CODE:
589 request = (netsnmp_request_info *) SvIV(SvRV(me));
590 request->repeat = newrepeat;
591
592 int
593 nari_setValue(me, type, value)
594 SV *me;
595 int type;
596 SV *value;
597 PREINIT:
598 netsnmp_request_info *request;
599 u_long utmp;
600 long ltmp;
601 uint64_t ulltmp;
602 struct counter64 c64;
603 oid myoid[MAX_OID_LEN];
604 size_t myoid_len;
605 STRLEN stringlen;
606 char * stringptr;
607 CODE:
608 request = (netsnmp_request_info *) SvIV(SvRV(me));
609 switch(type) {
610 case SNMP_NOSUCHINSTANCE :
611 snmp_set_var_typed_value(request->requestvb,SNMP_NOSUCHINSTANCE,0,0) ;
612 RETVAL = 1;
613 break ;
614 case SNMP_NOSUCHOBJECT :
615 snmp_set_var_typed_value(request->requestvb,SNMP_NOSUCHOBJECT,0,0) ;
616 RETVAL = 1;
617 break ;
618 case SNMP_ENDOFMIBVIEW :
619 snmp_set_var_typed_value(request->requestvb,SNMP_ENDOFMIBVIEW,0,0) ;
620 RETVAL = 1;
621 break ;
622 case ASN_INTEGER:
623 /* We want an integer here */
624 if ((SvTYPE(value) == SVt_IV) || (SvTYPE(value) == SVt_PVMG) ||
625 SvIOK(value)) {
626 /* Good - got a real one (or a blessed object that we hope will turn out OK) */
627 ltmp = SvIV(value);
628 snmp_set_var_typed_value(request->requestvb, (u_char)type,
629 (u_char *) <mp, sizeof(ltmp));
630 RETVAL = 1;
631 break;
632 }
633 else if (SvPOKp(value)) {
634 /* Might be OK - got a string, so try to convert it, allowing base 10, octal, and hex forms */
635 stringptr = SvPV(value, stringlen);
636 ltmp = strtol( stringptr, NULL, 0 );
637 if (errno == EINVAL) {
638 snmp_log(LOG_ERR, "Could not convert string to number in setValue: '%s'", stringptr);
639 RETVAL = 0;
640 break;
641 }
642
643 snmp_set_var_typed_value(request->requestvb, (u_char)type,
644 (u_char *) <mp, sizeof(ltmp));
645 RETVAL = 1;
646 break;
647 }
648 else {
649 snmp_log(LOG_ERR, "Non-integer value passed to setValue with ASN_INTEGER: type was %lu\n",
650 (unsigned long)SvTYPE(value));
651 RETVAL = 0;
652 break;
653 }
654
655
656 case ASN_UNSIGNED:
657 case ASN_COUNTER:
658 case ASN_TIMETICKS:
659 /* We want an integer here */
660 if ((SvTYPE(value) == SVt_IV) || (SvTYPE(value) == SVt_PVMG) ||
661 SvIOK(value)) {
662 /* Good - got a real one (or a blessed scalar which we have to hope will turn out OK) */
663 utmp = SvIV(value);
664 snmp_set_var_typed_value(request->requestvb, (u_char)type,
665 (u_char *) &utmp, sizeof(utmp));
666 RETVAL = 1;
667 break;
668 }
669 else if (SvPOKp(value)) {
670 /* Might be OK - got a string, so try to convert it, allowing base 10, octal, and hex forms */
671 stringptr = SvPV(value, stringlen);
672 utmp = strtoul( stringptr, NULL, 0 );
673 if (errno == EINVAL) {
674 snmp_log(LOG_ERR, "Could not convert string to number in setValue: '%s'", stringptr);
675 RETVAL = 0;
676 break;
677 }
678
679 snmp_set_var_typed_value(request->requestvb, (u_char)type,
680 (u_char *) &utmp, sizeof(utmp));
681 RETVAL = 1;
682 break;
683 }
684 else {
685 snmp_log(LOG_ERR, "Non-unsigned-integer value passed to setValue with ASN_UNSIGNED/ASN_COUNTER/ASN_TIMETICKS: type was %lu\n",
686 (unsigned long)SvTYPE(value));
687 RETVAL = 0;
688 break;
689 }
690
691 case ASN_COUNTER64:
692 /* We want an integer here */
693 if ((SvTYPE(value) == SVt_IV) || (SvTYPE(value) == SVt_PVMG)) {
694 /* Good - got a real one (or a blessed scalar which we have to hope will turn out OK) */
695 ulltmp = SvIV(value);
696 RETVAL = 1;
697 }
698 else if (SvPOKp(value)) {
699 /* Might be OK - got a string, so try to convert it, allowing base 10, octal, and hex forms */
700 stringptr = SvPV(value, stringlen);
701 errno = 0;
702 ulltmp = strtoull( stringptr, NULL, 0 );
703 if (errno != 0) {
704 snmp_log(LOG_ERR, "Could not convert string to number in setValue: '%s'", stringptr);
705 RETVAL = 0;
706 } else
707
708 RETVAL = 1;
709 }
710 else {
711 snmp_log(LOG_ERR, "Non-unsigned-integer value passed to setValue with ASN_COUNTER64: type was %lu\n",
712 (unsigned long)SvTYPE(value));
713 RETVAL = 0;
714 }
715 if (RETVAL) {
716 c64.high = (uint32_t)(ulltmp >> 32);
717 c64.low = (uint32_t)(ulltmp >> 0);
718 snmp_set_var_typed_value(request->requestvb, (u_char)type,
719 (u_char *) &c64, sizeof(struct counter64));
720 }
721 break;
722
723 case ASN_OCTET_STR:
724 case ASN_BIT_STR:
725 case ASN_OPAQUE:
726 /* Check that we have been passed something with a string value (or a blessed scalar) */
727 if (!SvPOKp(value) && (SvTYPE(value) != SVt_PVMG)) {
728 snmp_log(LOG_ERR, "Non-string value passed to setValue with ASN_OCTET_STR/ASN_BIT_STR: type was %lu\n",
729 (unsigned long)SvTYPE(value));
730 RETVAL = 0;
731 break;
732 }
733
734 /* Find length of string (strlen will *not* do, as these are binary strings) */
735 stringptr = SvPV(value, stringlen);
736
737 snmp_set_var_typed_value(request->requestvb, (u_char)type,
738 (u_char *) stringptr,
739 stringlen);
740 RETVAL = 1;
741 break;
742
743 case ASN_IPADDRESS:
744 /* IP addresses are passed as *binary* strings.
745 * In the case of IPv4 addresses, these are 4 bytes long.
746 * NOTE: the use of binary strings rather than dotted-quad or FQDNs was
747 * introduced here by Andrew Findlay's patch of March 17th 2003,
748 * and is effectively a change to the previous implied API which assumed
749 * the value was a (valid) hostname.
750 * Responsibility for decoding and resolving has been passed up to the Perl script.
751 */
752
753 /* Check that we have been passed something with a string value (or a blessed scalar) */
754 if (!SvPOKp(value) && (SvTYPE(value) != SVt_PVMG)) {
755 snmp_log(LOG_ERR, "Non-string value passed to setValue with ASN_IPADDRESS: type was %lu\n",
756 (unsigned long)SvTYPE(value));
757 RETVAL = 0;
758 break;
759 }
760
761 /* Find length of string (strlen will *not* do, as these are binary strings) */
762 stringptr = SvPV(value, stringlen);
763
764 # snmp_log(LOG_ERR, "IP address returned with length %d: %u.%u.%u.%u\n", stringlen, stringptr[0],
765 # stringptr[1], stringptr[2], stringptr[3] );
766
767 # Sanity check on address length
768 if ((stringlen != 4) && (stringlen != 16)) {
769 snmp_log(LOG_ERR, "IP address of %" NETSNMP_PRIz "d bytes passed to setValue with ASN_IPADDRESS\n", stringlen);
770 RETVAL = 0;
771 break;
772 }
773
774 snmp_set_var_typed_value(request->requestvb, (u_char)type,
775 stringptr, stringlen);
776 RETVAL = 1;
777 break;
778
779 case ASN_OBJECT_ID:
780 /* Check that we have been passed something with a string value (or a blessed scalar) */
781 if (!SvPOKp(value) && (SvTYPE(value) != SVt_PVMG)) {
782 snmp_log(LOG_ERR, "Non-string value passed to setValue with ASN_OBJECT_ID: type was %lu\n",
783 (unsigned long)SvTYPE(value));
784 RETVAL = 0;
785 break;
786 }
787
788 /* Extract the string */
789 stringptr = SvPV(value, stringlen);
790
791 /* snmp_log(LOG_ERR, "setValue returning OID '%s'\n", stringptr); */
792
793 myoid_len = MAX_OID_LEN;
794 if (!snmp_parse_oid(stringptr, myoid, &myoid_len)) {
795 snmp_log(LOG_ERR, "couldn't parse %s in setValue\n", stringptr);
796 RETVAL = 0;
797 break;
798 } else {
799 /* snmp_log(LOG_ERR, "setValue returning OID length %d\n", myoid_len); */
800
801 request = (netsnmp_request_info *) SvIV(SvRV(me));
802 snmp_set_var_typed_value(request->requestvb, (u_char)type,
803 (u_char *) myoid, (myoid_len * sizeof(myoid[0])) );
804 }
805
806 RETVAL = 1;
807 break;
808
809 default:
810 snmp_log(LOG_ERR, "unknown var value type: %d\n",
811 type);
812 RETVAL = 0;
813 break;
814 }
815
816 OUTPUT:
817 RETVAL
818
819 void
820 nari_setOID(me, value)
821 SV *me;
822 char *value;
823 PREINIT:
824 oid myoid[MAX_OID_LEN];
825 size_t myoid_len = MAX_OID_LEN;
826 netsnmp_request_info *request;
827 CODE:
828 myoid_len = MAX_OID_LEN;
829 if (!snmp_parse_oid(value, myoid, &myoid_len)) {
830 snmp_log(LOG_ERR, "couldn't parse %s in setOID\n", value);
831 } else {
832 request = (netsnmp_request_info *) SvIV(SvRV(me));
833 snmp_set_var_objid(request->requestvb, myoid, myoid_len);
834 }
835
836 void
837 nari_setError(me, rinfo, ecode)
838 SV *me;
839 SV *rinfo;
840 int ecode;
841 PREINIT:
842 netsnmp_request_info *request;
843 netsnmp_agent_request_info *reqinfo;
844 CODE:
845 request = (netsnmp_request_info *) SvIV(SvRV(me));
846 reqinfo = (netsnmp_agent_request_info *) SvIV(SvRV(rinfo));
847 netsnmp_set_request_error(reqinfo, request, ecode);
848
849 SV *
850 nari_next(me)
851 SV *me;
852 PREINIT:
853 netsnmp_request_info *request;
854 SV *arg, *rarg;
855 CODE:
856 {
857 request = (netsnmp_request_info *) SvIV(SvRV(me));
858 if (request && request->next) {
859 request = request->next;
860 rarg = newSViv(0);
861 arg = newSVrv(rarg, "NetSNMP::agent::netsnmp_request_infoPtr");
862 sv_setiv(arg, (IV) request);
863 RETVAL = rarg;
864 } else {
865 RETVAL = &sv_undef;
866 }
867 }
868 OUTPUT:
869 RETVAL
870
871 MODULE = NetSNMP::agent PACKAGE = NetSNMP::agent::netsnmp_agent_request_info PREFIX = narqi_
872
873
874 SV *
875 narqi_getSourceIp(me)
876 SV *me;
877 PREINIT:
878 netsnmp_agent_request_info *reqinfo;
879 netsnmp_udp_addr_pair *addr_pair;
880 struct sockaddr_in *from;
881 SV *rarg;
882
883 CODE:
884 reqinfo = (netsnmp_agent_request_info *) SvIV(SvRV(me));
885
886 /* XXX: transport-specific: UDP/IPv4 only! */
887 addr_pair = (netsnmp_udp_addr_pair *) (reqinfo->asp->pdu->transport_data);
888 from = (struct sockaddr_in *) &(addr_pair->remote_addr);
889 rarg = newSVpv((const char *)(&from->sin_addr.s_addr), sizeof(from->sin_addr.s_addr));
890 RETVAL = rarg;
891 OUTPUT:
892 RETVAL
893
894
895 SV *
896 narqi_getDestIp(me)
897 SV *me;
898 PREINIT:
899 netsnmp_agent_request_info *reqinfo;
900 netsnmp_udp_addr_pair *addr_pair;
901 struct in_addr *to;
902 SV *rarg;
903
904 CODE:
905 reqinfo = (netsnmp_agent_request_info *) SvIV(SvRV(me));
906
907 /* XXX: transport-specific: UDP/IPv4 only! */
908 addr_pair = (netsnmp_udp_addr_pair *) (reqinfo->asp->pdu->transport_data);
909 to = (struct in_addr *) &(addr_pair->local_addr);
910 rarg = newSVpv((const char *)(&to->s_addr), sizeof(to->s_addr));
911 RETVAL = rarg;
912 OUTPUT:
913 RETVAL
914
915 int
916 narqi_getMode(me)
917 SV *me;
918 PREINIT:
919 netsnmp_agent_request_info *reqinfo;
920 CODE:
921 reqinfo = (netsnmp_agent_request_info *) SvIV(SvRV(me));
922 RETVAL = reqinfo->mode;
923 OUTPUT:
924 RETVAL
925
926 void
927 narqi_setMode(me, newvalue)
928 SV *me;
929 int newvalue;
930 PREINIT:
931 netsnmp_agent_request_info *reqinfo;
932 CODE:
933 reqinfo = (netsnmp_agent_request_info *) SvIV(SvRV(me));
934 reqinfo->mode = newvalue;
935
936
937 MODULE = NetSNMP::agent PACKAGE = NetSNMP::agent
938
939