added files
[bcm963xx.git] / userapps / opensource / net-snmp / perl / agent / agent.xs
1 /* -*- C -*- */
2 #include "EXTERN.h"
3 #include "perl.h"
4 #include "XSUB.h"
5 #include <netdb.h>
6 #include <sys/socket.h>
7
8 #include <net-snmp/net-snmp-config.h>
9 #include <net-snmp/net-snmp-includes.h>
10 #include <net-snmp/agent/net-snmp-agent-includes.h>
11
12 #ifndef sv_undef
13 #define sv_undef PL_sv_undef
14 #endif
15
16 typedef struct handler_cb_data_s {
17    SV *perl_cb;
18 } handler_cb_data;
19
20 #define NETSNMP_NAMEBUF_LEN 128
21 typedef struct netsnmp_oid_s {
22     unsigned int        *name;
23     unsigned int         len;
24     unsigned int         namebuf[ NETSNMP_NAMEBUF_LEN ];
25 } netsnmp_oid;
26
27 static int have_done_agent = 0;
28 static int have_done_lib = 0;
29
30 static int
31 not_here(char *s)
32 {
33     croak("%s not implemented on this architecture", s);
34     return -1;
35 }
36
37 static double
38 constant_MODE_G(char *name, int len, int arg)
39 {
40     if (6 + 2 > len ) {
41         errno = EINVAL;
42         return 0;
43     }
44     switch (name[6 + 2]) {
45     case '\0':
46         if (strEQ(name + 6, "ET")) {    /* MODE_G removed */
47 #ifdef MODE_GET
48             return MODE_GET;
49 #else
50             goto not_there;
51 #endif
52         }
53     case 'B':
54         if (strEQ(name + 6, "ETBULK")) {        /* MODE_G removed */
55 #ifdef MODE_GETBULK
56             return MODE_GETBULK;
57 #else
58             goto not_there;
59 #endif
60         }
61     case 'N':
62         if (strEQ(name + 6, "ETNEXT")) {        /* MODE_G removed */
63 #ifdef MODE_GETNEXT
64             return MODE_GETNEXT;
65 #else
66             goto not_there;
67 #endif
68         }
69     }
70     errno = EINVAL;
71     return 0;
72
73 not_there:
74     errno = ENOENT;
75     return 0;
76 }
77
78 static double
79 constant_MODE_SET_R(char *name, int len, int arg)
80 {
81     if (10 + 6 >= len ) {
82         errno = EINVAL;
83         return 0;
84     }
85     switch (name[10 + 6]) {
86     case '1':
87         if (strEQ(name + 10, "ESERVE1")) {      /* MODE_SET_R removed */
88 #ifdef MODE_SET_RESERVE1
89             return MODE_SET_RESERVE1;
90 #else
91             goto not_there;
92 #endif
93         }
94     case '2':
95         if (strEQ(name + 10, "ESERVE2")) {      /* MODE_SET_R removed */
96 #ifdef MODE_SET_RESERVE2
97             return MODE_SET_RESERVE2;
98 #else
99             goto not_there;
100 #endif
101         }
102     }
103     errno = EINVAL;
104     return 0;
105
106 not_there:
107     errno = ENOENT;
108     return 0;
109 }
110
111 static double
112 constant_MODE_S(char *name, int len, int arg)
113 {
114     if (6 + 3 >= len ) {
115         errno = EINVAL;
116         return 0;
117     }
118     switch (name[6 + 3]) {
119     case 'A':
120         if (strEQ(name + 6, "ET_ACTION")) {     /* MODE_S removed */
121 #ifdef MODE_SET_ACTION
122             return MODE_SET_ACTION;
123 #else
124             goto not_there;
125 #endif
126         }
127     case 'B':
128         if (strEQ(name + 6, "ET_BEGIN")) {      /* MODE_S removed */
129 #ifdef MODE_SET_BEGIN
130             return MODE_SET_BEGIN;
131 #else
132             goto not_there;
133 #endif
134         }
135     case 'C':
136         if (strEQ(name + 6, "ET_COMMIT")) {     /* MODE_S removed */
137 #ifdef MODE_SET_COMMIT
138             return MODE_SET_COMMIT;
139 #else
140             goto not_there;
141 #endif
142         }
143     case 'F':
144         if (strEQ(name + 6, "ET_FREE")) {       /* MODE_S removed */
145 #ifdef MODE_SET_FREE
146             return MODE_SET_FREE;
147 #else
148             goto not_there;
149 #endif
150         }
151     case 'R':
152         if (!strnEQ(name + 6,"ET_", 3))
153             break;
154         return constant_MODE_SET_R(name, len, arg);
155     case 'U':
156         if (strEQ(name + 6, "ET_UNDO")) {       /* MODE_S removed */
157 #ifdef MODE_SET_UNDO
158             return MODE_SET_UNDO;
159 #else
160             goto not_there;
161 #endif
162         }
163     }
164     errno = EINVAL;
165     return 0;
166
167 not_there:
168     errno = ENOENT;
169     return 0;
170 }
171
172 static double
173 constant(char *name, int len, int arg)
174 {
175     errno = 0;
176     if (0 + 5 >= len ) {
177         errno = EINVAL;
178         return 0;
179     }
180     switch (name[0 + 5]) {
181     case 'G':
182         if (!strnEQ(name + 0,"MODE_", 5))
183             break;
184         return constant_MODE_G(name, len, arg);
185     case 'S':
186         if (!strnEQ(name + 0,"MODE_", 5))
187             break;
188         return constant_MODE_S(name, len, arg);
189     }
190     errno = EINVAL;
191     return 0;
192
193 not_there:
194     errno = ENOENT;
195     return 0;
196 }
197
198 int
199 handler_wrapper(netsnmp_mib_handler          *handler,
200                 netsnmp_handler_registration *reginfo,
201                 netsnmp_agent_request_info   *reqinfo,
202                 netsnmp_request_info         *requests) 
203 {
204     u_long intret = 5;
205     handler_cb_data *cb_data = (handler_cb_data *) handler->myvoid;
206     SV *cb;
207
208     if (cb_data && (cb = cb_data->perl_cb)) {
209         SV *arg;
210         SV *rarg;
211         dSP;
212         ENTER;
213         SAVETMPS;
214         PUSHMARK(sp);
215         rarg = newSViv(0);
216         arg = newSVrv(rarg, "NetSNMP::agent::netsnmp_mib_handler");
217         sv_setiv(arg, (int) handler);
218         XPUSHs(rarg);
219         rarg = newSViv(0);
220         arg = newSVrv(rarg, "NetSNMP::agent::reginfo");
221         sv_setiv(arg, (int) reginfo);
222         XPUSHs(rarg);
223         rarg = newSViv(0);
224         arg = newSVrv(rarg, "NetSNMP::agent::netsnmp_agent_request_info");
225         sv_setiv(arg, (int) reqinfo);
226         XPUSHs(rarg);
227         rarg = newSViv(0);
228         arg = newSVrv(rarg, "NetSNMP::agent::netsnmp_request_infoPtr");
229         sv_setiv(arg, (int) requests);
230         XPUSHs(rarg);
231         PUTBACK;
232         if (SvTYPE(cb) == SVt_PVCV) {
233             perl_call_sv(cb, G_DISCARD); /* I have no idea what discard does */
234                                          /* XXX: it discards the results,
235                                             which isn't right */
236         } else if (SvROK(cb) && SvTYPE(SvRV(cb)) == SVt_PVCV) {
237             /* reference to code */
238             perl_call_sv(SvRV(cb), G_DISCARD);
239         }
240         SPAGAIN;
241         PUTBACK;
242         FREETMPS;
243         LEAVE;
244     }
245     return SNMP_ERR_NOERROR;
246 }
247
248 MODULE = NetSNMP::agent         PACKAGE = NetSNMP::agent                
249
250 double
251 constant(sv,arg)
252     PREINIT:
253         STRLEN          len;
254     INPUT:
255         SV *            sv
256         char *          s = SvPV(sv, len);
257         int             arg
258     CODE:
259         RETVAL = constant(s,len,arg);
260     OUTPUT:
261         RETVAL
262
263 int
264 __agent_check_and_process(block = 1)
265         int block;
266     CODE:
267         RETVAL = agent_check_and_process(block);
268     OUTPUT:
269         RETVAL
270
271 void
272 init_mib()
273
274 int
275 init_agent(name)
276         const char *name;
277
278 void
279 init_snmp(name)
280         const char *name;
281
282 int
283 init_master_agent()
284
285 void    
286 snmp_enable_stderrlog()    
287
288 MODULE = NetSNMP::agent  PACKAGE = NetSNMP::agent PREFIX = na_
289
290 void
291 na_shutdown(me)
292     SV *me;
293     CODE:
294     {
295         snmp_shutdown("perl");
296     }
297
298 MODULE = NetSNMP::agent  PACKAGE = NetSNMP::agent::netsnmp_handler_registration  PREFIX = nsahr_
299
300 netsnmp_handler_registration *
301 nsahr_new(name, regoid, perlcallback)
302         char *name;
303         char *regoid;
304         SV   *perlcallback;
305     PREINIT:
306         oid myoid[MAX_OID_LEN];
307         size_t myoid_len = MAX_OID_LEN;
308         handler_cb_data *cb_data;
309         int gotit=1;
310     CODE:
311         if (!snmp_parse_oid(regoid, myoid, &myoid_len)) {
312             if (!read_objid(regoid, myoid, &myoid_len)) {
313                 fprintf(stderr, "couldn't parse %s (reg name: %s)\n",
314                         regoid, name);
315                 RETVAL = NULL;
316                 gotit = 0;
317             }
318         }
319         if (gotit) {
320             cb_data = (handler_cb_data *) malloc(sizeof(handler_cb_data));
321             RETVAL = netsnmp_create_handler_registration(name, handler_wrapper,
322                                                  myoid, myoid_len,
323                                                  HANDLER_CAN_RWRITE);
324             cb_data->perl_cb = newSVsv(perlcallback);
325             RETVAL->handler->myvoid = cb_data;
326         }
327     OUTPUT:
328         RETVAL
329
330 MODULE = NetSNMP::agent  PACKAGE = netsnmp_handler_registrationPtr  PREFIX = nsahr_
331
332 void
333 nsahr_DESTROY(reginfo)
334         netsnmp_handler_registration *reginfo
335     CODE:
336         netsnmp_handler_registration_free(reginfo);
337
338 int
339 nsahr_register(me)
340         SV *me;
341         PREINIT:
342         netsnmp_handler_registration *reginfo;
343         CODE:
344             {
345                 reginfo = (netsnmp_handler_registration *) SvIV(SvRV(me));
346                 RETVAL = netsnmp_register_handler(reginfo);
347                 if (!RETVAL) {
348                     /* the agent now has a "reference" to this reg pointer */
349                     SvREFCNT_inc(me);
350                 }
351             }
352     OUTPUT:
353         RETVAL
354
355 void
356 nsahr_getRootOID(me)
357     SV *me;
358     PREINIT:
359         int i;
360         netsnmp_oid *o;
361         netsnmp_handler_registration *reginfo;
362         SV *optr, *arg, *rarg;
363     PPCODE:
364     {
365         dSP;
366         PUSHMARK(SP);
367         reginfo = (netsnmp_handler_registration *) SvIV(SvRV(me));
368
369         o = SNMP_MALLOC_TYPEDEF(netsnmp_oid);
370         o->name = o->namebuf;
371         o->len = reginfo->rootoid_len;
372         memcpy(o->name, reginfo->rootoid,
373                reginfo->rootoid_len * sizeof(oid));
374
375         rarg = newSViv((int) 0);
376         arg = newSVrv(rarg, "netsnmp_oidPtr");
377         sv_setiv(arg, (int) o);
378
379         XPUSHs(rarg);
380
381         PUTBACK;
382         i = perl_call_pv("NetSNMP::OID::newwithptr", G_SCALAR);
383         SPAGAIN;
384         if (i != 1) {
385             fprintf(stderr, "unhandled OID error.\n");
386             /* ack XXX */
387         }
388         ST(0) = POPs;
389         XSRETURN(1);
390     }
391
392 MODULE = NetSNMP::agent  PACKAGE = NetSNMP::agent::netsnmp_request_infoPtr PREFIX = nari_
393
394 void
395 getOID(me)
396     SV *me;
397     PREINIT:
398         int i;
399         netsnmp_oid *o;
400         netsnmp_request_info *request;
401         SV *optr, *arg, *rarg;
402     PPCODE:
403     {
404         dSP;
405         PUSHMARK(SP);
406         request = (netsnmp_request_info *) SvIV(SvRV(me));
407
408         o = SNMP_MALLOC_TYPEDEF(netsnmp_oid);
409         o->name = o->namebuf;
410         o->len = request->requestvb->name_length;
411         memcpy(o->name, request->requestvb->name,
412                request->requestvb->name_length * sizeof(oid));
413
414         rarg = newSViv((int) 0);
415         arg = newSVrv(rarg, "netsnmp_oidPtr");
416         sv_setiv(arg, (int) o);
417
418         XPUSHs(rarg);
419
420         PUTBACK;
421         i = perl_call_pv("NetSNMP::OID::newwithptr", G_SCALAR);
422         SPAGAIN;
423         if (i != 1) {
424             fprintf(stderr, "unhandled OID error.\n");
425             /* ack XXX */
426         }
427         ST(0) = POPs;
428         XSRETURN(1);
429     }
430         
431 netsnmp_oid *
432 nari_getOIDptr(me)
433         SV *me;
434         PREINIT:
435         netsnmp_request_info *request;
436         CODE:
437         request = (netsnmp_request_info *) SvIV(SvRV(me));
438         RETVAL = SNMP_MALLOC_TYPEDEF(netsnmp_oid);
439         RETVAL->name = RETVAL->namebuf;
440         RETVAL->len = request->requestvb->name_length;
441         memcpy(RETVAL->name, request->requestvb->name,
442                request->requestvb->name_length * sizeof(oid));
443     OUTPUT:
444         RETVAL
445
446 char *
447 nari_getValue(me)
448         SV *me;
449     PREINIT:
450         u_char *oidbuf = NULL;
451         size_t ob_len = 0, oo_len = 0;
452         netsnmp_request_info *request;
453     CODE:
454         request = (netsnmp_request_info *) SvIV(SvRV(me));
455         sprint_realloc_by_type(&oidbuf, &ob_len, &oo_len, 1,
456                                request->requestvb, 0, 0, 0);
457         RETVAL = oidbuf; /* mem leak */
458     OUTPUT:
459         RETVAL
460
461 int
462 nari_getDelegated(me)
463         SV *me;
464     PREINIT:
465         netsnmp_request_info *request;
466     CODE:
467         request = (netsnmp_request_info *) SvIV(SvRV(me));
468         RETVAL = request->delegated;
469     OUTPUT:
470         RETVAL
471
472 void
473 nari_setDelegated(me, newdelegated)
474         SV *me;
475         int newdelegated;
476     PREINIT:
477         netsnmp_request_info *request;
478     CODE:
479         request = (netsnmp_request_info *) SvIV(SvRV(me));
480         request->delegated = newdelegated;
481
482 int
483 nari_getProcessed(me)
484         SV *me;
485     PREINIT:
486         netsnmp_request_info *request;
487     CODE:
488         request = (netsnmp_request_info *) SvIV(SvRV(me));
489         RETVAL = request->processed;
490     OUTPUT:
491         RETVAL
492
493 void
494 nari_setProcessed(me, newprocessed)
495         SV *me;
496         int newprocessed;
497     PREINIT:
498         netsnmp_request_info *request;
499     CODE:
500         request = (netsnmp_request_info *) SvIV(SvRV(me));
501         request->processed = newprocessed;
502
503 int
504 nari_getStatus(me)
505         SV *me;
506     PREINIT:
507         netsnmp_request_info *request;
508     CODE:
509         request = (netsnmp_request_info *) SvIV(SvRV(me));
510         RETVAL = request->status;
511     OUTPUT:
512         RETVAL
513
514 void
515 nari_setStatus(me, newstatus)
516         SV *me;
517         int newstatus;
518     PREINIT:
519         netsnmp_request_info *request;
520     CODE:
521         request = (netsnmp_request_info *) SvIV(SvRV(me));
522         request->status = newstatus;
523
524 int
525 nari_getRepeat(me)
526         SV *me;
527     PREINIT:
528         netsnmp_request_info *request;
529     CODE:
530         request = (netsnmp_request_info *) SvIV(SvRV(me));
531         RETVAL = request->repeat;
532     OUTPUT:
533         RETVAL
534
535 void
536 nari_setRepeat(me, newrepeat)
537         SV *me;
538         int newrepeat;
539     PREINIT:
540         netsnmp_request_info *request;
541     CODE:
542         request = (netsnmp_request_info *) SvIV(SvRV(me));
543         request->repeat = newrepeat;
544
545 int
546 nari_setValue(me, type, value)
547         SV *me;
548         int type;
549         char *value;
550     PREINIT:
551         u_char *oidbuf = NULL;
552         size_t ob_len = 0, oo_len = 0;
553         netsnmp_request_info *request;
554         u_long utmp;
555         struct hostent *hent;
556         long ltmp;
557         oid myoid[MAX_OID_LEN];
558         size_t myoid_len;
559     CODE:
560         request = (netsnmp_request_info *) SvIV(SvRV(me));
561         switch(type) {
562           case ASN_INTEGER:
563               ltmp = strtol(value, NULL, 0);
564               snmp_set_var_typed_value(request->requestvb, type,
565                                        (u_char *) &ltmp, sizeof(ltmp));
566               RETVAL = 1;
567               break;
568           case ASN_UNSIGNED:
569           case ASN_COUNTER:
570           case ASN_TIMETICKS:
571               utmp = strtoul(value, NULL, 0);
572               snmp_set_var_typed_value(request->requestvb, type,
573                                        (u_char *) &utmp, sizeof(utmp));
574               RETVAL = 1;
575               break;
576           case ASN_OCTET_STR:
577           case ASN_BIT_STR:
578               snmp_set_var_typed_value(request->requestvb, type,
579                                        (u_char *) value,
580                                        strlen(value)); /* XXX: null strs */
581               RETVAL = 1;
582               break;
583           case ASN_IPADDRESS:
584               hent = gethostbyname(value);
585               snmp_set_var_typed_value(request->requestvb, type,
586                                    hent->h_addr_list[0], 4); /* XXX: i4v6... */
587               RETVAL = 1;
588               break;
589           case ASN_OBJECT_ID:
590               if (!snmp_parse_oid(value, myoid, &myoid_len)) {
591                   fprintf(stderr, "couldn't parse %s in setOID\n", value);
592               } else {
593                   request = (netsnmp_request_info *) SvIV(SvRV(me));
594                   snmp_set_var_typed_value(request->requestvb, type,
595                                            (u_char *) myoid, myoid_len);
596               }
597               RETVAL = 1;
598               break;
599               
600             default:
601                 fprintf(stderr, "unknown var value type: %d (%s)\n",
602                         type, value);
603                 RETVAL = 0;
604                 break;
605         }
606
607     OUTPUT:
608         RETVAL
609         
610 void
611 nari_setOID(me, value)
612         SV *me;
613         char *value;
614     PREINIT:
615         oid myoid[MAX_OID_LEN];
616         size_t myoid_len = MAX_OID_LEN;
617         netsnmp_request_info *request;
618     CODE:
619         if (!snmp_parse_oid(value, myoid, &myoid_len)) {
620             fprintf(stderr, "couldn't parse %s in setOID\n", value);
621         } else {
622             request = (netsnmp_request_info *) SvIV(SvRV(me));
623             snmp_set_var_objid(request->requestvb, myoid, myoid_len);
624         }
625
626
627 SV *
628 nari_next(me)
629         SV *me;
630     PREINIT:
631         netsnmp_request_info *request;
632         SV *arg, *rarg;
633     CODE:
634         {
635             request = (netsnmp_request_info *) SvIV(SvRV(me));
636             if (request && request->next) {
637                 request = request->next;
638                 rarg = newSViv(0);
639                 arg = newSVrv(rarg, "NetSNMP::agent::netsnmp_request_infoPtr");
640                 sv_setiv(arg, (int) request);
641                 ST(0) = rarg;
642             } else {
643                 ST(0) = &sv_undef;
644             }
645         }
646
647 MODULE = NetSNMP::agent  PACKAGE = NetSNMP::agent::netsnmp_agent_request_info PREFIX = narqi_
648
649 int
650 narqi_getMode(me)
651         SV *me;
652     PREINIT:
653         netsnmp_agent_request_info *reqinfo;
654     CODE:
655         reqinfo = (netsnmp_agent_request_info *) SvIV(SvRV(me));
656         RETVAL = reqinfo->mode;
657     OUTPUT:
658         RETVAL
659
660 void
661 narqi_setMode(me, newvalue)
662         SV *me;
663         int newvalue;
664     PREINIT:
665         netsnmp_agent_request_info *reqinfo;
666     CODE:
667         reqinfo = (netsnmp_agent_request_info *) SvIV(SvRV(me));
668         reqinfo->mode = newvalue;
669         
670
671 MODULE = NetSNMP::agent         PACKAGE = NetSNMP::agent