Imported Upstream version 0.4.8
[platform/upstream/libsmi.git] / tools / dump-netsnmp.c
1 /*
2  * dump-netsnmp.c --
3  *
4  *      Operations to generate NET-SNMP mib module implementation code.
5  *
6  * Copyright (c) 1999 Frank Strauss, Technical University of Braunschweig.
7  * Copyright (c) 1999 J. Schoenwaelder, Technical University of Braunschweig.
8  *
9  * See the file "COPYING" for information on usage and redistribution
10  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11  *
12  * @(#) $Id: dump-netsnmp.c 8090 2008-04-18 12:56:29Z strauss $
13  */
14
15 /*
16  * TODO:
17  *        - assume that we build a dynamic loadable module
18  *        - update to 4.X version of the UCD API
19  *        - generate #defines for deprecated and obsolete objects
20  *        - generate stub codes for the various functions
21  *        - generate type and range checking code
22  */
23
24 #include <config.h>
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <ctype.h>
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif
33 #ifdef HAVE_WIN_H
34 #include "win.h"
35 #endif
36
37 #include "smi.h"
38 #include "smidump.h"
39
40
41 static int noMgrStubs = 0;
42 static int noAgtStubs = 0;
43
44
45 static char *getAccessString(SmiAccess access)
46 {
47     if (access == SMI_ACCESS_READ_WRITE) {
48         return "RWRITE";
49     } else if (access == SMI_ACCESS_READ_ONLY) {
50         return "RONLY";
51     } else {
52         return "";
53     }
54 }
55
56
57 static char *getBaseTypeString(SmiBasetype basetype)
58 {
59     switch(basetype) {
60     case SMI_BASETYPE_UNKNOWN:
61         return "ASN_NULL";
62     case SMI_BASETYPE_POINTER:
63         return "ASN_NULL";
64     case SMI_BASETYPE_INTEGER32:
65     case SMI_BASETYPE_ENUM:
66         return "ASN_INTEGER";
67     case SMI_BASETYPE_OCTETSTRING:
68     case SMI_BASETYPE_BITS:
69         return "ASN_OCTET_STR";
70     case SMI_BASETYPE_OBJECTIDENTIFIER:
71         return "ASN_OBJECT_ID";
72     case SMI_BASETYPE_UNSIGNED32:
73         return "ASN_INTEGER";
74     case SMI_BASETYPE_INTEGER64:
75         return "ASN_INTEGER";
76     case SMI_BASETYPE_UNSIGNED64:
77         return "ASN_INTEGER";
78     case SMI_BASETYPE_FLOAT32:
79     case SMI_BASETYPE_FLOAT64:
80     case SMI_BASETYPE_FLOAT128:
81         return "ASN_Real";
82     }
83
84     return NULL;
85 }
86
87
88
89 static char* translate(char *m)
90 {
91     char *s;
92     int i;
93
94     s = xstrdup(m);
95     for (i = 0; s[i]; i++) {
96         if (s[i] == '-') s[i] = '_';
97     }
98   
99     return s;
100 }
101
102
103
104 static char* translateUpper(char *m)
105 {
106     char *s;
107     int i;
108
109     s = xstrdup(m);
110     for (i = 0; s[i]; i++) {
111         if (s[i] == '-') s[i] = '_';
112         if (islower((int) s[i])) {
113             s[i] = toupper(s[i]);
114         }
115     }
116   
117     return s;
118 }
119
120
121
122 static char* translateLower(char *m)
123 {
124     char *s;
125     int i;
126
127     s = xstrdup(m);
128     for (i = 0; s[i]; i++) {
129         if (s[i] == '-') s[i] = '_';
130         if (isupper((int) s[i])) {
131             s[i] = tolower(s[i]);
132         }
133     }
134   
135     return s;
136 }
137
138
139
140 static char* translateFileName(char *m)
141 {
142     char *s;
143     int i;
144
145     s = xstrdup(m);
146     for (i = 0; s[i]; i++) {
147         if (s[i] == '_') s[i] = '-';
148         if (isupper((int) s[i])) {
149             s[i] = tolower(s[i]);
150         }
151     }
152   
153     return s;
154 }
155
156
157
158 static FILE * createFile(char *name, char *suffix)
159 {
160     char *fullname;
161     FILE *f;
162
163     fullname = xmalloc(strlen(name) + (suffix ? strlen(suffix) : 0) + 2);
164     strcpy(fullname, name);
165     if (suffix) {
166         strcat(fullname, suffix);
167     }
168     if (!access(fullname, R_OK)) {
169         fprintf(stderr, "smidump: %s already exists\n", fullname);
170         xfree(fullname);
171         return NULL;
172     }
173     f = fopen(fullname, "w");
174     if (!f) {
175         fprintf(stderr, "smidump: cannot open %s for writing: ", fullname);
176         perror(NULL);
177         xfree(fullname);
178         exit(1);
179     }
180     xfree(fullname);
181     return f;
182 }
183
184
185
186 static int isGroup(SmiNode *smiNode)
187 {
188     SmiNode *childNode;
189
190     if (smiNode->nodekind == SMI_NODEKIND_ROW) {
191         return 1;
192     }
193     
194     for (childNode = smiGetFirstChildNode(smiNode);
195          childNode;
196          childNode = smiGetNextChildNode(childNode)) {
197         if (childNode->nodekind == SMI_NODEKIND_SCALAR) {
198             return 1;
199         }
200     }
201
202     return 0;
203 }
204
205
206
207 static int isAccessible(SmiNode *groupNode)
208 {
209     SmiNode *smiNode;
210     int num = 0;
211     
212     for (smiNode = smiGetFirstChildNode(groupNode);
213          smiNode;
214          smiNode = smiGetNextChildNode(smiNode)) {
215         if ((smiNode->nodekind == SMI_NODEKIND_SCALAR
216              || smiNode->nodekind == SMI_NODEKIND_COLUMN)
217             && (smiNode->access == SMI_ACCESS_READ_ONLY
218                 || smiNode->access == SMI_ACCESS_READ_WRITE)) {
219             num++;
220         }
221     }
222
223     return num;
224 }
225
226
227
228 static void printHeaderTypedef(FILE *f, SmiModule *smiModule,
229                                SmiNode *groupNode)
230 {
231     SmiNode *smiNode;
232     SmiType *smiType;
233     char    *cModuleName, *cGroupName, *cName;
234     unsigned minSize, maxSize;
235
236     cModuleName = translateLower(smiModule->name);
237     cGroupName = translate(groupNode->name);
238
239     fprintf(f,
240             "/*\n"
241             " * C type definitions for %s::%s.\n"
242             " */\n\n",
243             smiModule->name, groupNode->name);
244     
245     fprintf(f, "typedef struct %s {\n", cGroupName);
246             
247     for (smiNode = smiGetFirstChildNode(groupNode);
248          smiNode;
249          smiNode = smiGetNextChildNode(smiNode)) {
250         if (smiNode->nodekind & (SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR)
251 #if 0
252             && (smiNode->access == SMI_ACCESS_READ_ONLY
253                 || smiNode->access == SMI_ACCESS_READ_WRITE)
254 #endif
255             ) {
256             smiType = smiGetNodeType(smiNode);
257             if (!smiType) {
258                 continue;
259             }
260             
261             cName = translate(smiNode->name);
262             switch (smiType->basetype) {
263             case SMI_BASETYPE_OBJECTIDENTIFIER:
264                 maxSize = smiGetMaxSize(smiType);
265                 minSize = smiGetMinSize(smiType);
266                 fprintf(f,
267                         "    uint32_t  *%s;\n", cName);
268                 if (maxSize != minSize) {
269                     fprintf(f,
270                             "    size_t    _%sLength;\n", cName);
271                 }
272                 break;
273             case SMI_BASETYPE_OCTETSTRING:
274             case SMI_BASETYPE_BITS:
275                 maxSize = smiGetMaxSize(smiType);
276                 minSize = smiGetMinSize(smiType);
277                 fprintf(f,
278                         "    u_char    *%s;\n", cName);
279                 if (maxSize != minSize) {
280                     fprintf(f,
281                             "    size_t    _%sLength;\n", cName);
282                 }
283                 break;
284             case SMI_BASETYPE_ENUM:
285             case SMI_BASETYPE_INTEGER32:
286                 fprintf(f,
287                         "    int32_t   *%s;\n", cName);
288                 break;
289             case SMI_BASETYPE_UNSIGNED32:
290                 fprintf(f,
291                         "    uint32_t  *%s;\n", cName);
292                 break;
293             case SMI_BASETYPE_INTEGER64:
294                 fprintf(f,
295                         "    int64_t   *%s; \n", cName);
296                 break;
297             case SMI_BASETYPE_UNSIGNED64:
298                 fprintf(f,
299                         "    uint64_t  *%s; \n", cName);
300                 break;
301             default:
302                 fprintf(f,
303                         "    /* ?? */  __%s; \n", cName);
304                 break;
305             }
306             xfree(cName);
307         }
308     }
309     
310     fprintf(f,
311             "    void      *_clientData;\t\t"
312             "/* pointer to client data structure */\n");
313     if (groupNode->nodekind == SMI_NODEKIND_ROW) {
314         fprintf(f, "    struct %s *_nextPtr;\t"
315                 "/* pointer to next table entry */\n", cGroupName);
316     }
317     fprintf(f,
318             "\n    /* private space to hold actual values */\n\n");
319
320     for (smiNode = smiGetFirstChildNode(groupNode);
321          smiNode;
322          smiNode = smiGetNextChildNode(smiNode)) {
323         if (smiNode->nodekind & (SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR)
324 #if 0
325             && (smiNode->access == SMI_ACCESS_READ_ONLY
326                 || smiNode->access == SMI_ACCESS_READ_WRITE)
327 #endif
328             ) {
329             smiType = smiGetNodeType(smiNode);
330             if (!smiType) {
331                 continue;
332             }
333             
334             cName = translate(smiNode->name);
335             switch (smiType->basetype) {
336             case SMI_BASETYPE_OBJECTIDENTIFIER:
337                 maxSize = smiGetMaxSize(smiType);
338                 fprintf(f,
339                         "    uint32_t  __%s[%u];\n", cName, maxSize);
340                 break;
341             case SMI_BASETYPE_OCTETSTRING:
342             case SMI_BASETYPE_BITS:
343                 maxSize = smiGetMaxSize(smiType);
344                 fprintf(f,
345                         "    u_char    __%s[%u];\n", cName, maxSize);
346                 break;
347             case SMI_BASETYPE_ENUM:
348             case SMI_BASETYPE_INTEGER32:
349                 fprintf(f,
350                         "    int32_t   __%s;\n", cName);
351                 break;
352             case SMI_BASETYPE_UNSIGNED32:
353                 fprintf(f,
354                         "    uint32_t  __%s;\n", cName);
355                 break;
356             case SMI_BASETYPE_INTEGER64:
357                 fprintf(f,
358                         "    int64_t   __%s; \n", cName);
359                 break;
360             case SMI_BASETYPE_UNSIGNED64:
361                 fprintf(f,
362                         "    uint64_t  __%s; \n", cName);
363                 break;
364             default:
365                 fprintf(f,
366                         "    /* ?? */  __%s; \n", cName);
367                 break;
368             }
369             xfree(cName);
370         }
371     }
372
373     fprintf(f, "} %s_t;\n\n", cGroupName);
374
375     fprintf(f,
376             "/*\n"
377             " * C manager interface stubs for %s::%s.\n"
378             " */\n\n",
379             smiModule->name, groupNode->name);
380             
381     fprintf(f, "extern int\n"
382             "%s_mgr_get_%s(struct snmp_session *s, %s_t **%s);\n",
383             cModuleName, cGroupName, cGroupName, cGroupName);
384     fprintf(f, "\n");
385
386     fprintf(f,
387             "/*\n"
388             " * C agent interface stubs for %s::%s.\n"
389             " */\n\n",
390             smiModule->name, groupNode->name);
391     
392     fprintf(f, "extern int\n"
393             "%s_agt_read_%s(%s_t *%s);\n",
394             cModuleName, cGroupName, cGroupName, cGroupName);
395     fprintf(f, "extern int\n"
396             "%s_agt_register_%s();\n\n",
397             cModuleName, cGroupName);
398     xfree(cGroupName);
399     xfree(cModuleName);
400 }
401
402
403
404 static void printHeaderTypedefs(FILE *f, SmiModule *smiModule)
405 {
406     SmiNode   *smiNode;
407     int       cnt = 0;
408     char      *cModuleName;
409     char      *cSmiNodeName;
410     
411     for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
412          smiNode;
413          smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
414         if (isGroup(smiNode) && isAccessible(smiNode)) {
415             cnt++;
416             printHeaderTypedef(f, smiModule, smiNode);
417         }
418     }
419     
420     if (cnt) {
421         fprintf(f, "\n");
422     }
423
424     if (cnt) {
425         /*
426          * Should this go into the agent implementation module?
427          */
428         cModuleName = translateLower(smiModule->name);
429         fprintf(f, "typedef struct %s {\n", cModuleName);
430         for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
431              smiNode;
432              smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
433             if (isGroup(smiNode) && isAccessible(smiNode)) {
434                 cSmiNodeName = translate(smiNode->name);
435                 if (smiNode->nodekind == SMI_NODEKIND_ROW) {
436                     fprintf(f, "    %s_t\t*%s;\n", cSmiNodeName, cSmiNodeName);
437                 } else {
438                     fprintf(f, "    %s_t\t%s;\n", cSmiNodeName, cSmiNodeName);
439                 }
440                 xfree(cSmiNodeName);
441             }
442         }
443         fprintf(f, "} %s_t;\n\n", cModuleName);
444         xfree(cModuleName);
445     }
446 }
447
448
449
450 static void dumpHeader(SmiModule *smiModule, char *baseName)
451 {
452     char        *pModuleName;
453     char        *cModuleName;
454     FILE        *f;
455
456     pModuleName = translateUpper(smiModule->name);
457
458     f = createFile(baseName, ".h");
459     if (! f) {
460         return;
461     }
462     
463     fprintf(f,
464             "/*\n"
465             " * This C header file has been generated by smidump "
466             SMI_VERSION_STRING ".\n"
467             " * It is intended to be used with the NET-SNMP package.\n"
468             " *\n"
469             " * This header is derived from the %s module.\n"
470             " *\n * $I" "d$\n"
471             " */\n\n", smiModule->name);
472
473     fprintf(f, "#ifndef _%s_H_\n", pModuleName);
474     fprintf(f, "#define _%s_H_\n\n", pModuleName);
475
476     fprintf(f, "#include <stdlib.h>\n\n");
477
478     fprintf(f,
479             "#ifdef HAVE_STDINT_H\n"
480             "#include <stdint.h>\n"
481             "#endif\n\n");
482
483     printHeaderTypedefs(f, smiModule);
484
485     fprintf(f,
486             "/*\n"
487             " * Initialization function:\n"
488             " */\n\n");
489     cModuleName = translateLower(smiModule->name);
490     fprintf(f, "void %s_agt_init(void);\n\n", cModuleName);
491     xfree(cModuleName);
492
493     fprintf(f, "#endif /* _%s_H_ */\n", pModuleName);
494
495     fclose(f);
496     xfree(pModuleName);
497 }
498
499
500
501 static void printAgtReadMethodDecls(FILE *f, SmiModule *smiModule)
502 {
503     SmiNode   *smiNode;
504     int       cnt = 0;
505
506     for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
507          smiNode;
508          smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
509         if (isGroup(smiNode) && isAccessible(smiNode)) {
510             cnt++;
511             if (cnt == 1) {
512                 fprintf(f,
513                         "/*\n"
514                         " * Forward declaration of read methods for groups of scalars and tables:\n"
515                         " */\n\n");
516             }
517             fprintf(f,
518                     "static unsigned char *\nread_%s_stub(struct variable *,"
519                     " oid *, size_t *, int, size_t *, WriteMethod **);\n",
520                     smiNode->name);
521         }
522     }
523     
524     if (cnt) {
525         fprintf(f, "\n");
526     }
527 }
528
529
530
531 static void printAgtWriteMethodDecls(FILE *f, SmiModule *smiModule)
532 {
533     SmiNode     *smiNode;
534     int         cnt = 0;
535     
536     for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
537          smiNode;
538          smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
539         if (smiNode->access == SMI_ACCESS_READ_WRITE) {
540             cnt++;
541             if (cnt == 1) {
542                 fprintf(f,
543                         "/*\n"
544                         " * Forward declaration of write methods for writable objects:\n"
545                         " */\n\n");
546             }
547             fprintf(f,
548                     "static int\nwrite_%s_stub(int,"
549                     " u_char *, u_char, int, u_char *, oid *, int);\n",
550                     smiNode->name);
551         }
552     }
553     
554     if (cnt) {
555         fprintf(f, "\n");
556     }
557 }
558
559
560
561 static void printAgtDefinesGroup(FILE *f, SmiNode *groupNode, int cnt)
562 {
563     char         *cName, *cGroupName;
564     SmiNode      *smiNode;
565     SmiType      *smiType;
566     int          num = 0;
567     unsigned int i;
568     
569     if (cnt == 1) {
570         fprintf(f,
571         "/*\n"
572         " * Definitions of tags that are used internally to read/write\n"
573         " * the selected object type. These tags should be unique.\n"
574         " */\n\n");
575     }
576
577     cGroupName = translate(groupNode->name);
578
579     for (smiNode = smiGetFirstChildNode(groupNode);
580          smiNode;
581          smiNode = smiGetNextChildNode(smiNode)) {
582         if (smiNode->nodekind & (SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR)
583             && (smiNode->access == SMI_ACCESS_READ_ONLY
584                 || smiNode->access == SMI_ACCESS_READ_WRITE)) {
585             num++;
586             cName = translateUpper(smiNode->name);
587             fprintf(f, "#define %-32s %d\n", cName,
588                     smiNode->oid[smiNode->oidlen-1]);
589             xfree(cName);
590         }
591     }
592     fprintf(f, "\n");
593
594     if (num) {
595         fprintf(f, "static oid %s_base[] = {", cGroupName);
596         for (i = 0; i < groupNode->oidlen; i++) {
597             fprintf(f, "%s%d", i ? ", " : "", groupNode->oid[i]);
598         }
599         fprintf(f, "};\n\n");
600         fprintf(f, "struct variable %s_variables[] = {\n", cGroupName);
601         for (smiNode = smiGetFirstChildNode(groupNode);
602              smiNode;
603              smiNode = smiGetNextChildNode(smiNode)) {
604             if (smiNode->nodekind & (SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR)
605                 && (smiNode->access == SMI_ACCESS_READ_ONLY
606                     || smiNode->access == SMI_ACCESS_READ_WRITE)) {
607                 smiType = smiGetNodeType(smiNode);
608                 if (!smiType) {
609                     continue;
610                 }
611                 cName = translateUpper(smiNode->name);
612                 fprintf(f, "    { %s, %s, %s, read_%s_stub, %d, {%d} },\n",
613                         cName, getBaseTypeString(smiType->basetype),
614                         getAccessString(smiNode->access),
615                         cGroupName, 1, smiNode->oid[smiNode->oidlen-1]);
616                 xfree(cName);
617             }
618         }
619         fprintf(f, "};\n\n");
620     }
621
622     xfree(cGroupName);
623 }
624
625
626
627 static void printAgtDefines(FILE *f, SmiModule *smiModule)
628 {
629     SmiNode   *smiNode;
630     int       cnt = 0;
631     
632     for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
633          smiNode;
634          smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
635         if (isGroup(smiNode)) {
636             printAgtDefinesGroup(f, smiNode, ++cnt);
637         }
638     }
639     
640     if (cnt) {
641         fprintf(f, "\n");
642     }
643 }
644
645
646
647 static void printAgtRegister(FILE *f, SmiNode *groupNode, int cnt)
648 {
649     SmiNode *smiNode;
650     char    *cGroupName;
651     int     num = 0;
652
653     for (smiNode = smiGetFirstChildNode(groupNode);
654          smiNode;
655          smiNode = smiGetNextChildNode(smiNode)) {
656         if (smiNode->nodekind & (SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR)
657             && (smiNode->access == SMI_ACCESS_READ_ONLY
658                 || smiNode->access == SMI_ACCESS_READ_WRITE)) {
659             num++;
660         }
661     }
662     fprintf(f, "\n");
663
664     if (cnt == 1) {
665         fprintf(f,
666                 "/*\n"
667                 " * Registration functions for the various MIB groups.\n"
668                 " */\n\n");
669     }
670     
671     cGroupName = translate(groupNode->name);
672
673     fprintf(f, "int register_%s()\n{\n", cGroupName);
674     fprintf(f,
675             "    return register_mib(\"%s\",\n"
676             "         %s_variables,\n"
677             "         sizeof(struct variable),\n"
678             "         sizeof(%s_variables)/sizeof(struct variable),\n"
679             "         %s_base,\n"
680             "         sizeof(%s_base)/sizeof(oid));\n",
681             cGroupName, cGroupName, cGroupName, cGroupName, cGroupName);
682     fprintf(f, "};\n\n");
683
684     xfree(cGroupName);
685 }
686
687
688
689 static void printAgtInit(FILE *f, SmiModule *smiModule)
690 {
691     SmiNode   *smiNode;
692     int       cnt = 0;
693
694     for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
695          smiNode;
696          smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
697         if (isGroup(smiNode)) {
698             printAgtRegister(f, smiNode, ++cnt);
699         }
700     }
701
702     if (cnt) {
703         fprintf(f, "\n");
704     }
705 }
706
707
708
709 static void printAgtReadMethod(FILE *f, SmiNode *groupNode)
710 {
711     SmiNode   *smiNode;
712     SmiType   *smiType;
713     char      *cName, *sName, *lName;
714
715     sName = translate(groupNode->name);
716
717     fprintf(f,
718             "static unsigned char *\nread_%s_stub(struct variable *vp,\n"
719             "    oid     *name,\n"
720             "    size_t  *length,\n"
721             "    int     exact,\n"
722             "    size_t  *var_len,\n"
723             "    WriteMethod **write_method)\n"
724             "{\n", sName);
725
726     fprintf(f, "    static %s_t %s;\n\n", sName, sName);
727     
728     smiNode = smiGetFirstChildNode(groupNode);
729     if (smiNode && smiNode->nodekind == SMI_NODEKIND_SCALAR) {
730         fprintf(f,
731                 "    /* check whether the instance identifier is valid */\n"
732                 "\n"
733                 "    if (header_generic(vp, name, length, exact, var_len,\n"
734                 "                       write_method) == MATCH_FAILED) {\n"
735                 "        return NULL;\n"
736                 "    }\n"
737                 "\n");
738     }
739
740     fprintf(f,
741             "    /* call the user supplied function to retrieve values */\n"
742             "\n"
743             "    read_%s(&%s);\n"
744             "\n", sName, sName);
745
746     fprintf(f,
747             "    /* return the current value of the variable */\n"
748             "\n"
749             "    switch (vp->magic) {\n"
750             "\n");
751
752     for (smiNode = smiGetFirstChildNode(groupNode);
753          smiNode;
754          smiNode = smiGetNextChildNode(smiNode)) {
755         if (smiNode->nodekind & (SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR)
756             && (smiNode->access == SMI_ACCESS_READ_ONLY
757                 || smiNode->access == SMI_ACCESS_READ_WRITE)) {
758             cName = translateUpper(smiNode->name);
759             lName = translate(smiNode->name);
760             smiType = smiGetNodeType(smiNode);
761             if (! smiType) {
762                 continue;
763             }
764             fprintf(f, "    case %s:\n", cName);
765             switch (smiType->basetype) {
766             case SMI_BASETYPE_OBJECTIDENTIFIER:
767                 fprintf(f,
768                         "        *var_len = %s._%sLength;\n"
769                         "        return (unsigned char *) %s.%s;\n",
770                         sName, lName, sName, lName);
771                 break;
772             case SMI_BASETYPE_OCTETSTRING:
773             case SMI_BASETYPE_BITS:
774                 fprintf(f,
775                         "        *var_len = %s._%sLength;\n"
776                         "        return (unsigned char *) %s.%s;\n",
777                         sName, lName, sName, lName);
778                 break;
779             case SMI_BASETYPE_ENUM:
780             case SMI_BASETYPE_INTEGER32:
781             case SMI_BASETYPE_UNSIGNED32:
782                 fprintf(f,
783                         "        return (unsigned char *) &%s.%s;\n",
784                         sName, lName);
785                 break;
786             default:
787                 fprintf(f,
788                         "        /* add code to return the value here */\n");
789             }
790             fprintf(f, "\n");
791             xfree(cName);
792             xfree(lName);
793         }
794     }
795
796     fprintf(f,
797             "    default:\n"
798             "         ERROR_MSG(\"\");\n"
799             "    }\n"
800             "\n"
801             "    return NULL;\n"
802             "}\n"
803             "\n");
804
805     xfree(sName);
806 }
807
808
809
810 static void printAgtReadMethods(FILE *f, SmiModule *smiModule)
811 {
812     SmiNode   *smiNode;
813     int       cnt = 0;
814     
815     for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
816          smiNode;
817          smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
818         if (isGroup(smiNode) && isAccessible(smiNode)) {
819             cnt++;
820             if (cnt == 1) {
821                 fprintf(f,
822                         "/*\n"
823                         " * Read methods for groups of scalars and tables:\n"
824                         " */\n\n");
825             }
826             printAgtReadMethod(f, smiNode);
827         }
828     }
829     
830     if (cnt) {
831         fprintf(f, "\n");
832     }
833 }
834
835
836
837 static void printAgtWriteMethods(FILE *f, SmiModule *smiModule)
838 {
839     SmiNode     *smiNode;
840     int         cnt = 0;
841     
842     for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
843          smiNode;
844          smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
845         if (smiNode->access == SMI_ACCESS_READ_WRITE) {
846             cnt++;
847             if (cnt == 1) {
848                 fprintf(f,
849                         "/*\n"
850                         " * Forward declaration of write methods for writable objects:\n"
851                         " */\n\n");
852             }
853             fprintf(f,
854                     "static int\nwrite_%s_stub(int action,\n"
855                     "    u_char   *var_val,\n"
856                     "    u_char   var_val_type,\n"
857                     "    int      var_val_len,\n"
858                     "    u_char   *statP,\n"
859                     "    oid      *name,\n"
860                     "    int      name_len)\n"
861                     "{\n", smiNode->name);
862             fprintf(f,
863                     "    return SNMP_ERR_NOERROR;\n"
864                     "}\n\n");
865         }
866     }
867     
868     if (cnt) {
869         fprintf(f, "\n");
870     }
871 }
872
873
874
875 static void dumpAgtStub(SmiModule *smiModule, char *baseName)
876 {
877     char        *stubModuleName;
878     FILE        *f;
879
880     stubModuleName = xmalloc(strlen(baseName) + 10);
881     strcpy(stubModuleName, baseName);
882     strcat(stubModuleName, "-agt-stub");
883     
884     f = createFile(stubModuleName, ".c");
885     if (! f) {
886         xfree(stubModuleName);
887         return;
888     }
889
890     fprintf(f,
891             "/*\n"
892             " * This C file has been generated by smidump "
893             SMI_VERSION_STRING ".\n"
894             " * It is intended to be used with the NET-SNMP agent library.\n"
895             " *\n"
896             " * This C file is derived from the %s module.\n"
897             " *\n * $I" "d$\n"
898             " */\n\n", smiModule->name );
899         
900     fprintf(f,
901             "#include <stdio.h>\n"
902             "#include <string.h>\n"
903             "#include <malloc.h>\n"
904             "\n"
905             "#include \"%s.h\"\n"
906             "\n"
907             "#include <ucd-snmp/asn1.h>\n"
908             "#include <ucd-snmp/snmp.h>\n"
909             "#include <ucd-snmp/snmp_api.h>\n"
910             "#include <ucd-snmp/snmp_impl.h>\n"
911             "#include <ucd-snmp/snmp_vars.h>\n"
912             "\n",
913             baseName);
914
915     printAgtReadMethodDecls(f, smiModule);
916     printAgtWriteMethodDecls(f, smiModule);
917     printAgtDefines(f, smiModule);
918     printAgtInit(f, smiModule);
919
920     printAgtReadMethods(f, smiModule);
921     printAgtWriteMethods(f, smiModule);
922
923     fclose(f);
924     xfree(stubModuleName);
925 }
926
927
928
929 static void printMgrOidDefinitions(FILE *f, SmiModule *smiModule)
930 {
931     SmiNode      *smiNode;
932     char         *cName;
933     unsigned int i;
934     
935     for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
936          smiNode;
937          smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
938         if (smiNode->nodekind & (SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR)
939             && smiNode->access != SMI_ACCESS_NOTIFY) {
940             cName = translate(smiNode->name);
941             fprintf(f, "static oid %s[] = {", cName);
942             for (i = 0; i < smiNode->oidlen; i++) {
943                 fprintf(f, "%s%u", i ? ", " : "", smiNode->oid[i]);
944             }
945             fprintf(f, "};\n");
946             xfree(cName);
947         }
948     }
949     fprintf(f, "\n");
950 }
951
952
953
954 static void printMgrGetScalarAssignement(FILE *f, SmiNode *groupNode)
955 {
956     SmiNode *smiNode;
957     SmiType *smiType;
958     char    *cGroupName, *cName;
959     unsigned maxSize, minSize;
960
961     cGroupName = translate(groupNode->name);
962
963     for (smiNode = smiGetFirstChildNode(groupNode);
964          smiNode;
965          smiNode = smiGetNextChildNode(smiNode)) {
966         if (smiNode->nodekind & (SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR)
967             && (smiNode->access == SMI_ACCESS_READ_ONLY
968                 || smiNode->access == SMI_ACCESS_READ_WRITE)) {
969
970             smiType = smiGetNodeType(smiNode);
971             if (!smiType) {
972                 continue;
973             }
974             
975             cName = translate(smiNode->name);
976             fprintf(f,
977                     "        if (vars->name_length > sizeof(%s)/sizeof(oid)\n"
978                     "            && memcmp(vars->name, %s, sizeof(%s)) == 0) {\n",
979                     cName, cName, cName);
980             switch (smiType->basetype) {
981             case SMI_BASETYPE_INTEGER32:
982             case SMI_BASETYPE_UNSIGNED32:
983             case SMI_BASETYPE_ENUM:
984                 fprintf(f,
985                         "            (*%s)->__%s = *vars->val.integer;\n"
986                         "            (*%s)->%s = &((*%s)->__%s);\n",
987                         cGroupName, cName,
988                         cGroupName, cName, cGroupName, cName);
989                 break;
990             case SMI_BASETYPE_OCTETSTRING:
991             case SMI_BASETYPE_BITS:
992                 maxSize = smiGetMaxSize(smiType);
993                 minSize = smiGetMinSize(smiType);
994                 fprintf(f,
995                         "            memcpy((*%s)->__%s, vars->val.string, vars->val_len);\n",
996                         cGroupName, cName);
997                 if (minSize != maxSize) {
998                     fprintf(f,
999                             "            (*%s)->_%sLength = vars->val_len;\n",
1000                             cGroupName, cName);
1001                 }
1002                 fprintf(f,
1003                         "            (*%s)->%s = (*%s)->__%s;\n",
1004                         cGroupName, cName, cGroupName, cName);
1005                 break;
1006             case SMI_BASETYPE_OBJECTIDENTIFIER:
1007                 break;
1008             default:
1009                 break;
1010             }
1011             fprintf(f,
1012                     "        }\n");
1013             xfree(cName);
1014         }
1015     }
1016
1017     xfree(cGroupName);
1018 }
1019
1020
1021
1022 static void printMgrGetMethod(FILE *f, SmiModule *smiModule,
1023                               SmiNode *groupNode)
1024 {
1025     SmiNode *smiNode;
1026     char    *cModuleName, *cGroupName;
1027
1028     cModuleName = translateLower(smiModule->name);
1029     cGroupName = translate(groupNode->name);
1030
1031     fprintf(f,
1032             "int %s_mgr_get_%s(struct snmp_session *s, %s_t **%s)\n"
1033             "{\n"
1034             "    struct snmp_session *peer;\n"
1035             "    struct snmp_pdu *request, *response;\n"
1036             "    struct variable_list *vars;\n"
1037             "    int status;\n"
1038             "\n",
1039             cModuleName, cGroupName, cGroupName, cGroupName);
1040
1041     fprintf(f,
1042             "    request = snmp_pdu_create(SNMP_MSG_GETNEXT);\n");
1043             
1044     for (smiNode = smiGetFirstChildNode(groupNode);
1045          smiNode;
1046          smiNode = smiGetNextChildNode(smiNode)) {
1047         if (smiNode->nodekind & (SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR)
1048             && (smiNode->access == SMI_ACCESS_READ_ONLY
1049                 || smiNode->access == SMI_ACCESS_READ_WRITE)) {
1050             fprintf(f,
1051             "    snmp_add_null_var(request, %s, sizeof(%s)/sizeof(oid));\n",
1052                     smiNode->name, smiNode->name);
1053         }
1054     }
1055
1056     fprintf(f,
1057             "\n"
1058             "    peer = snmp_open(s);\n"
1059             "    if (!peer) {\n"
1060             "        snmp_free_pdu(request);\n"
1061             "        return -1;\n"
1062             "    }\n"
1063             "\n"
1064             "    status = snmp_synch_response(peer, request, &response);\n"
1065             "    if (status != STAT_SUCCESS) {\n"
1066             "        if (response) snmp_free_pdu(response);\n"
1067             "        snmp_close(peer);\n"
1068             "        return -2;\n"
1069             "    }\n"
1070             "\n");
1071
1072     /* generate code for error checking and handling */
1073
1074     fprintf(f,
1075             "    *%s = (%s_t *) malloc(sizeof(%s_t));\n"
1076             "    if (! *%s) {\n"
1077             "        if (response) snmp_free_pdu(response);\n"
1078             "        snmp_close(peer);\n"
1079             "        return -4;\n"
1080             "    }\n"
1081             "\n",
1082             cGroupName, cGroupName, cGroupName, cGroupName);
1083
1084     fprintf(f,
1085             "    for (vars = response->variables; vars; vars = vars->next_variable) {\n");
1086     printMgrGetScalarAssignement(f, groupNode);
1087     fprintf(f,
1088             "    }\n"
1089             "\n");
1090
1091
1092 #if 0
1093     if (response->errstat != SNMP_ERR_NOERROR) {
1094         return -3;
1095     }
1096
1097     /* copy to data structures */
1098
1099     /* cleanup */
1100
1101 #endif
1102
1103     fprintf(f,
1104             "    if (response) snmp_free_pdu(response);\n"
1105             "\n"
1106             "    if (snmp_close(peer) == 0) {\n"
1107             "        return -5;\n"
1108             "    }\n"
1109             "\n"
1110             "    return 0;\n"
1111             "}\n\n");
1112
1113     xfree(cGroupName);
1114     xfree(cModuleName);
1115 }
1116  
1117
1118
1119
1120 static void printMgrGetMethods(FILE *f, SmiModule *smiModule)
1121 {
1122     SmiNode   *smiNode;
1123     int       cnt = 0;
1124     
1125     for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
1126          smiNode;
1127          smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
1128         if (isGroup(smiNode) && isAccessible(smiNode)) {
1129             cnt++;
1130             printMgrGetMethod(f, smiModule, smiNode);
1131         }
1132     }
1133     
1134     if (cnt) {
1135         fprintf(f, "\n");
1136     }
1137 }
1138
1139
1140
1141 static void dumpMgrStub(SmiModule *smiModule, char *baseName)
1142 {
1143     char        *stubModuleName;
1144     FILE        *f;
1145
1146     stubModuleName = xmalloc(strlen(baseName) + 10);
1147     strcpy(stubModuleName, baseName);
1148     strcat(stubModuleName, "-mgr-stub");
1149     
1150     f = createFile(stubModuleName, ".c");
1151     if (! f) {
1152         xfree(stubModuleName);
1153         return;
1154     }
1155
1156     fprintf(f,
1157             "/*\n"
1158             " * This C file has been generated by smidump "
1159             SMI_VERSION_STRING ".\n"
1160             " * It is intended to be used with the NET-SNMP library.\n"
1161             " *\n"
1162             " * This C file is derived from the %s module.\n"
1163             " *\n * $I" "d$\n"
1164             " */\n\n", smiModule->name );
1165         
1166     fprintf(f,
1167             "#include <stdlib.h>\n"
1168             "\n"
1169             "#include <ucd-snmp/asn1.h>\n"
1170             "#include <ucd-snmp/snmp.h>\n"
1171             "#include <ucd-snmp/snmp_api.h>\n"
1172             "#include <ucd-snmp/snmp_client.h>\n"
1173             "\n"
1174             "#include \"%s.h\"\n"
1175             "\n",
1176             baseName);
1177
1178     printMgrOidDefinitions(f, smiModule);
1179     
1180     printMgrGetMethods(f, smiModule);
1181     
1182     if (fflush(f) || ferror(f)) {
1183         perror("smidump: write error");
1184         exit(1);
1185     }
1186
1187     fclose(f);
1188     xfree(stubModuleName);
1189 }
1190
1191
1192
1193 static void dumpAgtImpl(SmiModule *smiModule, char *baseName)
1194 {
1195     char        *stubModuleName, *cModuleName;
1196     FILE        *f;
1197
1198     stubModuleName = xmalloc(strlen(baseName) + 10);
1199     strcpy(stubModuleName, baseName);
1200     strcat(stubModuleName, "-agt");
1201     
1202
1203     f = createFile(stubModuleName, ".c");
1204     if (! f) {
1205         xfree(stubModuleName);
1206         return;
1207     }
1208
1209     cModuleName = translateLower(smiModule->name);
1210
1211     fprintf(f,
1212             "/*\n"
1213             " * This C file has been generated by smidump "
1214             SMI_VERSION_STRING ".\n"
1215             " * It is intended to be used with the NET-SNMP agent library.\n"
1216             " *\n"
1217             " * This C file is derived from the %s module.\n"
1218             " *\n * $I" "d$\n"
1219             " */\n\n", smiModule->name );
1220         
1221     fprintf(f,
1222             "#include <stdio.h>\n"
1223             "#include <string.h>\n"
1224             "#include <malloc.h>\n"
1225             "\n"
1226             "#include \"%s.h\"\n"
1227             "\n"
1228             "#include <ucd-snmp/asn1.h>\n"
1229             "#include <ucd-snmp/snmp.h>\n"
1230             "#include <ucd-snmp/snmp_api.h>\n"
1231             "#include <ucd-snmp/snmp_impl.h>\n"
1232             "#include <ucd-snmp/snmp_vars.h>\n"
1233             "\n",
1234             baseName);
1235
1236     fprintf(f,
1237             "static oid %s_caps[] = {0,0};\n"
1238             "\n",
1239             cModuleName);
1240
1241     fprintf(f,
1242             "void init_%s(void)\n"
1243             "{\n"
1244 #if 0
1245             /* create an entry in the sysORTable */
1246             
1247             register_sysORTable(if_mib_caps, sizeof(if_mib_caps),
1248                                 "IF-MIB implementation version 0.0.");
1249             
1250             /* register the various parts of the MIB */
1251             
1252             register_interfaces();
1253             register_ifEntry();
1254             
1255             /* register essential callbacks */
1256             
1257             snmp_register_callback(SNMP_CALLBACK_LIBRARY,
1258                                    SNMP_CALLBACK_SHUTDOWN,
1259                                    term_if_mib, NULL);
1260 #endif
1261             "}\n"
1262             "\n",
1263             cModuleName);
1264
1265
1266     fprintf(f,
1267             "void deinit_%s()\n"
1268             "{\n"
1269             "    unregister_sysORTable(%s_caps, sizeof(%s_caps));\n"
1270             "}\n"
1271             "\n",
1272             cModuleName, cModuleName, cModuleName);
1273
1274     fprintf(f,
1275             "int term_%s()\n"
1276             "{\n"
1277             "    deinit_%s();\n"
1278             "    return 0;\n"
1279             "}\n"
1280             "\n",
1281             cModuleName, cModuleName);
1282
1283     xfree(cModuleName);
1284     
1285     if (fflush(f) || ferror(f)) {
1286         perror("smidump: write error");
1287         exit(1);
1288     }
1289
1290     fclose(f);
1291     xfree(stubModuleName);
1292 }
1293
1294
1295
1296 static void dumpNetSnmp(int modc, SmiModule **modv, int flags, char *output)
1297 {
1298     char        *baseName;
1299     int         i;
1300
1301     if (flags & SMIDUMP_FLAG_UNITE) {
1302         /* not implemented yet */
1303     } else {
1304         for (i = 0; i < modc; i++) {
1305             baseName = output ? output : translateFileName(modv[i]->name);
1306             dumpHeader(modv[i], baseName);
1307             if (! noAgtStubs) {
1308                 dumpAgtStub(modv[i], baseName);
1309                 dumpAgtImpl(modv[i], baseName);
1310             }
1311             if (! noMgrStubs) {
1312                 dumpMgrStub(modv[i], baseName);
1313             }
1314             if (! output) xfree(baseName);
1315         }
1316     }
1317
1318 }
1319
1320
1321
1322 void initNetsnmp()
1323 {
1324     static SmidumpDriverOption opt[] = {
1325         { "no-mgr-stubs", OPT_FLAG, &noMgrStubs, 0,
1326           "do not generate manager stub code"},
1327         { "no-agt-stubs", OPT_FLAG, &noAgtStubs, 0,
1328           "do not generate agent stub code"},
1329         { 0, OPT_END, 0, 0 }
1330     };
1331
1332     static SmidumpDriver driver = {
1333         "netsnmp",
1334         dumpNetSnmp,
1335         SMI_FLAG_NODESCR,
1336         SMIDUMP_DRIVER_CANT_UNITE,
1337         "ANSI C code for the NET-SNMP package",
1338         opt,
1339         NULL
1340     };
1341
1342     smidumpRegisterDriver(&driver);
1343 }