/*
* dump-scli.c --
*
* Operations to generate MIB module stubs for the scli package.
*
* Copyright (c) 2001 J. Schoenwaelder, Technical University of Braunschweig.
* Copyright (c) 2002 J. Schoenwaelder, University of Osnabrueck.
* Copyright (c) 2004 J. Schoenwaelder, International University Bremen.
*
* See the file "COPYING" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* @(#) $Id: dump-scli.c 8090 2008-04-18 12:56:29Z strauss $
*/
/*
* TODO:
* - range checks for 64 bit numbers
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_WIN_H
#include "win.h"
#endif
#include "smi.h"
#include "smidump.h"
#include <sys/types.h>
#ifdef HAVE_REGEX_H
#include <regex.h>
#else
#define regex_t int
#define regcomp(a, b, c) 1
#define regexec(a, b, c, d, e) 0
#define regerror(a,b,c,d) strncpy(c, "regex not supported", d)
#define regfree(a)
#endif
static char *prefix = NULL;
static char *include = NULL;
static char *exclude = NULL;
static int sflag = 0;
static int cflag = 0;
static int dflag = 0;
static regex_t _incl_regex, *incl_regex = NULL;
static regex_t _excl_regex, *excl_regex = NULL;
static char *keywords_c99[] = {
"auto", "enum", "restrict", "unsigned",
"break", "extern", "return", "void",
"case", "float", "short", "volatile",
"char", "for", "signed", "while",
"const", "goto", "sizeof", "_Bool",
"continue", "if", "static", "_Complex",
"default", "inline", "struct", "_Imaginary",
"do", "int", "switch",
"double", "long", "typedef",
"else", "register", "union",
NULL
};
static int
isKeyword(char *m)
{
int i;
for (i = 0; keywords_c99[i]; i++) {
if (strcmp(m, keywords_c99[i]) == 0) {
return 1;
}
}
return 0;
}
static char *
getStringTime(time_t t)
{
static char s[27];
struct tm *tm;
tm = gmtime(&t);
sprintf(s, "%04d-%02d-%02d %02d:%02d",
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min);
return s;
}
static void
fprintCommentString(FILE *f, char *s)
{
int i, len;
if (s) {
fprintf(f, " * ");
len = strlen(s);
for (i = 0; i < len; i++) {
fputc(s[i], f);
if (s[i] == '\n') {
fprintf(f, " * ");
}
}
fputc('\n', f);
}
}
static void
fprintTopComment(FILE *f, SmiModule *smiModule)
{
SmiRevision *smiRevision;
char *date;
fprintf(f,
"/* \t\t\t\t\t\t-- DO NOT EDIT --\n"
" * Generated by smidump version " SMI_VERSION_STRING ":\n");
fprintf(f, " * smidump -f scli");
if (sflag) {
fprintf(f, " --scli-set");
}
if (cflag) {
fprintf(f, " --scli-create");
}
if (dflag) {
fprintf(f, " --scli-delete");
}
if (prefix) {
fprintf(f, " \\\n * --scli-prefix='%s'", prefix);
}
if (include) {
fprintf(f, " \\\n * --scli-include='%s'", include);
}
if (exclude) {
fprintf(f, " \\\n * --scli-exclude='%s'", exclude);
}
fprintf(f, " %s\n *\n", smiModule->name);
fprintf(f,
" * Derived from %s:\n", smiModule->name);
fprintCommentString(f, smiModule->description);
for (smiRevision = smiGetFirstRevision(smiModule);
smiRevision;
smiRevision = smiGetNextRevision(smiRevision)) {
date = getStringTime(smiRevision->date);
fprintf(f,
" *\n"
" * Revision %s:\n", date);
fprintCommentString(f, smiRevision->description);
}
#if 0
if (smiModule->organization || smiModule->contactinfo) {
fprintf(f, " *\n * Contact:\n");
printCommentString(f, smiModule->organization);
fprintf(f, " *\n");
printCommentString(f, smiModule->contactinfo);
}
#endif
fprintf(f,
" *\n * $I" "d$\n"
" */\n"
"\n");
}
static char*
translate(char *m)
{
char *s;
int i;
s = xstrdup(m);
for (i = 0; s[i]; i++) {
if (s[i] == '-') s[i] = '_';
}
while (isKeyword(s)) {
s = xrealloc(s, strlen(s) + 2);
strcat(s, "_");
}
return s;
}
static char*
translateUpper(char *m)
{
char *s;
int i;
s = xstrdup(m);
for (i = 0; s[i]; i++) {
if (s[i] == '-') s[i] = '_';
if (islower((int) s[i])) {
s[i] = toupper(s[i]);
}
}
while (isKeyword(s)) {
s = xrealloc(s, strlen(s) + 2);
strcat(s, "_");
}
return s;
}
static char*
translateLower(char *m)
{
char *s;
int i;
s = xstrdup(m);
for (i = 0; s[i]; i++) {
if (s[i] == '-') s[i] = '_';
if (isupper((int) s[i])) {
s[i] = tolower(s[i]);
}
}
while (isKeyword(s)) {
s = xrealloc(s, strlen(s) + 2);
strcat(s, "_");
}
return s;
}
static char*
translateFileName(char *m)
{
char *s;
int i;
s = xstrdup(m);
for (i = 0; s[i]; i++) {
if (s[i] == '_') s[i] = '-';
if (isupper((int) s[i])) {
s[i] = tolower(s[i]);
}
}
return s;
}
static FILE *
createFile(char *name, char *suffix)
{
char *fullname;
FILE *f;
fullname = xmalloc(strlen(name) + (suffix ? strlen(suffix) : 0) + 2);
strcpy(fullname, name);
if (suffix) {
strcat(fullname, suffix);
}
if (!access(fullname, R_OK)) {
fprintf(stderr, "smidump: %s already exists\n", fullname);
xfree(fullname);
return NULL;
}
f = fopen(fullname, "w");
if (!f) {
fprintf(stderr, "smidump: cannot open %s for writing: ", fullname);
perror(NULL);
xfree(fullname);
exit(1);
}
xfree(fullname);
return f;
}
static int
isGroup(SmiNode *smiNode, SmiNodekind memberkind)
{
SmiNode *childNode;
int status;
if (incl_regex) {
if (! smiNode->name) {
return 0;
}
status = regexec(incl_regex, smiNode->name, (size_t) 0, NULL, 0);
if (status != 0) {
return 0;
}
}
if (excl_regex) {
if (! smiNode->name) {
return 0;
}
status = regexec(excl_regex, smiNode->name, (size_t) 0, NULL, 0);
if (status == 0) {
return 0;
}
}
for (childNode = smiGetFirstChildNode(smiNode);
childNode;
childNode = smiGetNextChildNode(childNode)) {
if (childNode->nodekind & memberkind) {
return 1;
}
}
return 0;
}
static int
isAccessible(SmiNode *groupNode)
{
SmiNode *smiNode;
int num = 0;
for (smiNode = smiGetFirstChildNode(groupNode);
smiNode;
smiNode = smiGetNextChildNode(smiNode)) {
if ((smiNode->nodekind == SMI_NODEKIND_SCALAR
|| smiNode->nodekind == SMI_NODEKIND_COLUMN)
&& (smiNode->access == SMI_ACCESS_READ_ONLY
|| smiNode->access == SMI_ACCESS_READ_WRITE)) {
num++;
}
}
return num;
}
static int
isIndex(SmiNode *groupNode, SmiNode *smiNode)
{
SmiElement *smiElement;
/*
* Perhaps this test needs to be more sophisticated if you have
* really creative cross-table indexing constructions...
*/
for (smiElement = smiGetFirstElement(groupNode);
smiElement; smiElement = smiGetNextElement(smiElement)) {
if (smiNode == smiGetElementNode(smiElement)) {
return 1;
}
}
return 0;
}
static int
isWritable(SmiNode *treeNode, SmiNodekind nodekind)
{
SmiNode *smiNode;
for (smiNode = smiGetFirstChildNode(treeNode);
smiNode;
smiNode = smiGetNextChildNode(smiNode)) {
if (smiNode->nodekind & (nodekind)
&& (smiNode->access >= SMI_ACCESS_READ_WRITE)) {
break;
}
}
return (smiNode != NULL);
}
static char*
getSnmpType(SmiType *smiType)
{
struct {
char *module;
char *name;
char *tag;
} typemap[] = {
{ "RFC1155-SMI","Counter", "GNET_SNMP_VARBIND_TYPE_COUNTER32" },
{ "SNMPv2-SMI", "Counter32", "GNET_SNMP_VARBIND_TYPE_COUNTER32" },
{ "RFC1155-SMI","TimeTicks", "GNET_SNMP_VARBIND_TYPE_TIMETICKS" },
{ "SNMPv2-SMI", "TimeTicks", "GNET_SNMP_VARBIND_TYPE_TIMETICKS" },
{ "RFC1155-SMI","Opaque", "GNET_SNMP_VARBIND_TYPE_OPAQUE" },
{ "SNMPv2-SMI", "Opaque", "GNET_SNMP_VARBIND_TYPE_OPAQUE" },
{ "RFC1155-SMI","IpAddress", "GNET_SNMP_VARBIND_TYPE_IPADDRESS" },
{ "SNMPv2-SMI", "IpAddress", "GNET_SNMP_VARBIND_TYPE_IPADDRESS" },
{ NULL, NULL, NULL }
};
SmiBasetype basetype = smiType->basetype;
do {
int i;
for (i = 0; typemap[i].name; i++) {
if (smiType->name
&& (strcmp(smiType->name, typemap[i].name) == 0)) {
return typemap[i].tag;
}
}
} while ((smiType = smiGetParentType(smiType)));
switch (basetype) {
case SMI_BASETYPE_INTEGER32:
case SMI_BASETYPE_ENUM:
return "GNET_SNMP_VARBIND_TYPE_INTEGER32";
case SMI_BASETYPE_UNSIGNED32:
return "GNET_SNMP_VARBIND_TYPE_UNSIGNED32";
case SMI_BASETYPE_INTEGER64:
return NULL;
case SMI_BASETYPE_UNSIGNED64:
return "GNET_SNMP_VARBIND_TYPE_COUNTER64";
case SMI_BASETYPE_OCTETSTRING:
return "GNET_SNMP_VARBIND_TYPE_OCTETSTRING";
case SMI_BASETYPE_BITS:
return "GNET_SNMP_VARBIND_TYPE_OCTETSTRING";
case SMI_BASETYPE_OBJECTIDENTIFIER:
return "GNET_SNMP_VARBIND_TYPE_OBJECTID";
case SMI_BASETYPE_FLOAT32:
case SMI_BASETYPE_FLOAT64:
case SMI_BASETYPE_FLOAT128:
return NULL;
case SMI_BASETYPE_UNKNOWN:
return NULL;
case SMI_BASETYPE_POINTER:
return NULL;
}
return NULL;
}
typedef void (*ForEachIndexFunc) (FILE *f, SmiNode *groupNode, SmiNode *smiNode, int flags, int maxlen, char *name);
/*
* Check whether we have duplicate nodes in the INDEX. If yes,
* generate a unique name.
*/
static char*
getIndexName(SmiNode *indexNode, SmiNode *iNode, SmiElement *smiElement)
{
SmiElement *se;
SmiNode *sn;
int n = 0, m = 0, tail = 0;
char *name;
for (se = smiGetFirstElement(indexNode);
se; se = smiGetNextElement(se)) {
sn = smiGetElementNode(se);
if (strcmp(sn->name, iNode->name) == 0) {
n++;
if (! tail) m++;
}
if (se == smiElement) tail = 1;
}
if (n > 1) {
smiAsprintf(&name, "%s%d", iNode->name, m);
} else {
name = xstrdup(iNode->name);
}
return name;
}
static void
foreachIndexDo(FILE *f, SmiNode *smiNode, ForEachIndexFunc func,
int flags, int maxlen)
{
SmiNode *indexNode = NULL, *iNode;
SmiElement *smiElement;
switch (smiNode->indexkind) {
case SMI_INDEX_INDEX:
case SMI_INDEX_REORDER:
indexNode = smiNode;
break;
case SMI_INDEX_EXPAND: /* TODO: we have to do more work here! */
break;
case SMI_INDEX_AUGMENT:
case SMI_INDEX_SPARSE:
indexNode = smiGetRelatedNode(smiNode);
break;
case SMI_INDEX_UNKNOWN:
break;
}
if (indexNode) {
for (smiElement = smiGetFirstElement(indexNode);
smiElement; smiElement = smiGetNextElement(smiElement)) {
iNode = smiGetElementNode(smiElement);
if (iNode) {
char *name = getIndexName(indexNode, iNode, smiElement);
(func) (f, smiNode, iNode, flags, maxlen, name);
if (name) xfree(name);
}
}
}
}
static void
printIndexParamsFunc(FILE *f, SmiNode *smiNode, SmiNode *iNode,
int flags, int maxlen, char *name)
{
SmiType *iType;
char *cName;
unsigned minSize, maxSize;
iType = smiGetNodeType(iNode);
if (! iType) {
return;
}
cName = translate(name ? name : iNode->name);
switch (iType->basetype) {
case SMI_BASETYPE_OBJECTIDENTIFIER:
maxSize = smiGetMaxSize(iType);
minSize = smiGetMinSize(iType);
fprintf(f, ", %s%s", flags ? "guint32 *" : "", cName);
if (minSize != maxSize) {
fprintf(f, ", %s_%sLength",
flags ? "guint16 " : "", cName);
}
break;
case SMI_BASETYPE_OCTETSTRING:
case SMI_BASETYPE_BITS:
maxSize = smiGetMaxSize(iType);
minSize = smiGetMinSize(iType);
fprintf(f, ", %s%s", flags ? "guchar *" : "", cName);
if (minSize != maxSize) {
fprintf(f, ", %s_%sLength",
flags ? "guint16 " : "", cName);
}
break;
case SMI_BASETYPE_ENUM:
case SMI_BASETYPE_INTEGER32:
fprintf(f, ", %s%s", flags ? "gint32 " : "", cName);
break;
case SMI_BASETYPE_UNSIGNED32:
fprintf(f, ", %s%s", flags ? "guint32 " : "", cName);
break;
default:
fprintf(f, "/* ?? %s */", cName);
break;
}
xfree(cName);
}
static void
printIndexParamsPassFunc(FILE *f, SmiNode *smiNode, SmiNode *iNode,
int flags, int maxlen, char *name)
{
SmiType *iType;
char *cName, *gName;
unsigned minSize, maxSize;
iType = smiGetNodeType(iNode);
if (! iType) {
return;
}
gName = translate(smiNode->name);
cName = translate(iNode->name);
fprintf(f, ", %s->%s", gName, cName);
switch (iType->basetype) {
case SMI_BASETYPE_BITS:
case SMI_BASETYPE_OCTETSTRING:
case SMI_BASETYPE_OBJECTIDENTIFIER:
maxSize = smiGetMaxSize(iType);
minSize = smiGetMinSize(iType);
if (minSize != maxSize) {
fprintf(f, ", %s->_%sLength", gName, cName);
}
break;
default:
break;
}
xfree(cName);
xfree(gName);
}
static void
printIndexAssignmentFunc(FILE *f, SmiNode *smiNode, SmiNode *iNode,
int flags, int maxlen, char *name)
{
SmiType *iType;
char *cName, *gName, *dName, *dModuleName;
unsigned minSize, maxSize;
iType = smiGetNodeType(iNode);
if (! iType) {
return;
}
gName = translate(smiNode->name);
cName = translate(iNode->name);
dName = translateUpper(iNode->name);
dModuleName = translateUpper(smiGetNodeModule(iNode)->name);
switch (iType->basetype) {
case SMI_BASETYPE_OBJECTIDENTIFIER:
fprintf(f, " memcpy(%s->%s, %s, _%sLength * sizeof(guint32));\n",
gName, cName, cName, cName);
break;
case SMI_BASETYPE_OCTETSTRING:
case SMI_BASETYPE_BITS:
maxSize = smiGetMaxSize(iType);
minSize = smiGetMinSize(iType);
if (minSize != maxSize) {
fprintf(f, " memcpy(%s->%s, %s, _%sLength);\n",
gName, cName, cName, cName);
} else {
fprintf(f, " memcpy(%s->%s, %s, %s_%sLENGTH);\n",
gName, cName, cName, dModuleName, dName);
}
break;
case SMI_BASETYPE_ENUM:
case SMI_BASETYPE_INTEGER32:
case SMI_BASETYPE_UNSIGNED32:
fprintf(f, " %s->%s = %s;\n",
gName, cName, cName);
break;
default:
fprintf(f, " /* ?? %s */\n", cName);
break;
}
xfree(dModuleName);
xfree(dName);
xfree(cName);
xfree(gName);
}
static void
printHeaderEnumeration(FILE *f, SmiModule *smiModule,
SmiNode * smiNode, SmiType *smiType)
{
SmiNamedNumber *nn;
char *cName, *cPrefix;
char *dName, *dModuleName;
char *name;
int len;
if (smiType && smiType->name) {
name = smiType->name;
} else if (smiNode && smiNode->name) {
name = smiNode->name;
} else {
return;
}
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
dModuleName = translateUpper(smiModule->name);
cName = translate(name);
dName = translateUpper(name);
for (len = 0, nn = smiGetFirstNamedNumber(smiType); nn;
nn = smiGetNextNamedNumber(nn)) {
if (len < strlen(nn->name)) {
len = strlen(nn->name);
}
}
for (nn = smiGetFirstNamedNumber(smiType); nn;
nn = smiGetNextNamedNumber(nn)) {
char *dEnum = translateUpper(nn->name);
fprintf(f, "#define %s_%s_%-*s %d\n",
dModuleName, dName, len, dEnum,
(int) nn->value.value.integer32);
xfree(dEnum);
}
fprintf(f, "\nextern GNetSnmpEnum const %s_enums_%s[];\n\n",
cPrefix, cName);
xfree(dName);
xfree(cName);
xfree(dModuleName);
xfree(cPrefix);
}
static void
printHeaderEnumerations(FILE *f, SmiModule *smiModule)
{
SmiNode *smiNode, *parentNode;
SmiType *smiType;
int cnt = 0;
const unsigned int groupkind = SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN;
const char *header =
"/*\n"
" * Tables to map enumerations to strings and vice versa.\n"
" */\n"
"\n";
for (smiNode = smiGetFirstNode(smiModule, groupkind);
smiNode;
smiNode = smiGetNextNode(smiNode, groupkind)) {
parentNode = smiGetParentNode(smiNode);
if (! parentNode || ! isGroup(parentNode, groupkind)) {
continue;
}
smiType = smiGetNodeType(smiNode);
if (smiType && !smiType->name
&& smiType->basetype == SMI_BASETYPE_ENUM
&& smiGetTypeModule(smiType) == smiModule) {
if (! cnt) {
fputs(header, f);
}
cnt++;
printHeaderEnumeration(f, smiModule, smiNode, smiType);
}
}
for (smiType = smiGetFirstType(smiModule);
smiType;
smiType = smiGetNextType(smiType)) {
if (smiType->basetype == SMI_BASETYPE_ENUM
&& smiGetTypeModule(smiType) == smiModule) {
if (! cnt) {
fputs(header, f);
}
cnt++;
printHeaderEnumeration(f, smiModule, NULL, smiType);
}
}
if (cnt) {
fprintf(f, "\n");
}
}
static void
printHeaderIdentities(FILE *f, SmiModule *smiModule)
{
SmiNode *smiNode, *moduleIdentityNode, *parentNode;
int cnt = 0;
unsigned int i;
char *dName, *dModuleName;
char *cModuleName;
moduleIdentityNode = smiGetModuleIdentityNode(smiModule);
dModuleName = translateUpper(smiModule->name);
for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_NODE);
smiNode;
smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_NODE)) {
parentNode = smiGetParentNode(smiNode);
if (! parentNode || ! isGroup(parentNode, SMI_NODEKIND_NODE)) {
continue;
}
if (smiNode->status == SMI_STATUS_UNKNOWN) {
continue;
}
if (smiNode == moduleIdentityNode) {
continue;
}
if (! cnt) {
fprintf(f,
"/*\n"
" * Tables to map identities to strings and vice versa.\n"
" */\n"
"\n");
}
cnt++;
dName = translateUpper(smiNode->name);
fprintf(f, "#define %s_%s\t", dModuleName, dName);
for (i = 0; i < smiNode->oidlen; i++) {
fprintf(f, "%s%u", i ? "," : "", smiNode->oid[i]);
}
fprintf(f, "\n");
xfree(dName);
}
if (cnt) {
cModuleName = translateLower(smiModule->name);
fprintf(f,
"\n"
"extern GNetSnmpIdentity const %s_identities[];\n"
"\n",
cModuleName);
xfree(cModuleName);
}
xfree(dModuleName);
}
static void
printHeaderNotifications(FILE *f, SmiModule *smiModule)
{
SmiNode *smiNode;
int cnt = 0;
unsigned int i;
char *dName, *dModuleName;
char *cModuleName;
dModuleName = translateUpper(smiModule->name);
for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_NOTIFICATION);
smiNode;
smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_NOTIFICATION)) {
if (smiNode->status == SMI_STATUS_UNKNOWN) {
continue;
}
if (! cnt) {
fprintf(f,
"/*\n"
" * Tables to map notifications to strings and vice versa.\n"
" */\n"
"\n");
}
cnt++;
dName = translateUpper(smiNode->name);
fprintf(f, "#define %s_%s\t", dModuleName, dName);
for (i = 0; i < smiNode->oidlen; i++) {
fprintf(f, "%s%u", i ? "," : "", smiNode->oid[i]);
}
fprintf(f, "\n");
xfree(dName);
}
if (cnt) {
cModuleName = translateLower(smiModule->name);
fprintf(f,
"\n"
"extern GNetSnmpIdentity const %s_notifications[];\n"
"\n",
cModuleName);
xfree(cModuleName);
}
xfree(dModuleName);
}
static void
printParam(FILE *f, SmiNode *smiNode)
{
char *cName, *dNodeName, *dModuleName;
unsigned minSize, maxSize;
SmiType *smiType;
SmiModule *smiModule;
smiModule = smiGetNodeModule(smiNode);
smiType = smiGetNodeType(smiNode);
if (! smiType) {
return;
}
cName = translate(smiNode->name);
dNodeName = translateUpper(smiNode->name);
dModuleName = translateUpper(smiModule ? smiModule->name : "");
switch (smiType->basetype) {
case SMI_BASETYPE_OBJECTIDENTIFIER:
maxSize = smiGetMaxSize(smiType);
minSize = smiGetMinSize(smiType);
fprintf(f,
", guint32 *%s", cName);
if (maxSize != minSize) {
fprintf(f,
", guint16 _%sLength", cName);
}
break;
case SMI_BASETYPE_OCTETSTRING:
case SMI_BASETYPE_BITS:
maxSize = smiGetMaxSize(smiType);
minSize = smiGetMinSize(smiType);
fprintf(f,
", guchar *%s", cName);
if (maxSize != minSize) {
fprintf(f,
", guint16 _%sLength", cName);
}
break;
case SMI_BASETYPE_ENUM:
case SMI_BASETYPE_INTEGER32:
fprintf(f,
", gint32 %s", cName);
break;
case SMI_BASETYPE_UNSIGNED32:
fprintf(f,
", guint32 %s", cName);
break;
case SMI_BASETYPE_INTEGER64:
fprintf(f,
", gint64 %s", cName);
break;
case SMI_BASETYPE_UNSIGNED64:
fprintf(f,
", guint64 %s", cName);
break;
default:
fprintf(f,
" /* ?? */ _%s", cName);
break;
}
xfree(cName);
}
static void
printCreateMethodPrototype(FILE *f, SmiNode *groupNode)
{
SmiModule *smiModule;
char *cPrefix, *cNodeName;
smiModule = smiGetNodeModule(groupNode);
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
cNodeName = translate(groupNode->name);
fprintf(f,
"extern void\n"
"%s_create_%s(GNetSnmp *s", cPrefix, cNodeName);
foreachIndexDo(f, groupNode, printIndexParamsFunc, 1, 0);
fprintf(f, ");\n\n");
xfree(cNodeName);
xfree(cPrefix);
}
static void
printDeleteMethodPrototype(FILE *f, SmiNode *groupNode)
{
SmiModule *smiModule;
char *cPrefix, *cNodeName;
smiModule = smiGetNodeModule(groupNode);
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
cNodeName = translate(groupNode->name);
fprintf(f,
"extern void\n"
"%s_delete_%s(GNetSnmp *s", cPrefix, cNodeName);
foreachIndexDo(f, groupNode, printIndexParamsFunc, 1, 0);
fprintf(f, ");\n\n");
xfree(cNodeName);
xfree(cPrefix);
}
static void
printSetMethodPrototype(FILE *f, SmiNode *groupNode, SmiNode *smiNode)
{
SmiModule *smiModule;
char *cPrefix, *cNodeName;
smiModule = smiGetNodeModule(smiNode);
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
cNodeName = translate(smiNode->name);
fprintf(f,
"extern void\n"
"%s_set_%s(GNetSnmp *s",
cPrefix, cNodeName);
foreachIndexDo(f, groupNode, printIndexParamsFunc, 1, 0);
printParam(f, smiNode);
fprintf(f, ");\n\n");
xfree(cNodeName);
xfree(cPrefix);
}
static void
printMethodPrototypes(FILE *f, SmiNode *groupNode)
{
SmiNode *smiNode;
SmiType *smiType;
for (smiNode = smiGetFirstChildNode(groupNode);
smiNode;
smiNode = smiGetNextChildNode(smiNode)) {
if (smiNode->nodekind & (SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR)
&& (smiNode->access >= SMI_ACCESS_READ_ONLY)) {
if (smiNode->access == SMI_ACCESS_READ_WRITE) {
smiType = smiGetNodeType(smiNode);
if (smiType && smiType->name
&& strcmp(smiType->name, "RowStatus") == 0) {
if (cflag) printCreateMethodPrototype(f, groupNode);
if (dflag) printDeleteMethodPrototype(f, groupNode);
} else {
if (! isIndex(groupNode, smiNode)) {
if (sflag) printSetMethodPrototype(f, groupNode, smiNode);
}
}
}
}
}
}
static void
printHeaderTypedefMemberComment(FILE *f, SmiNode *smiNode, SmiType *smiType)
{
char *s = NULL;
switch (smiNode->access) {
case SMI_ACCESS_READ_WRITE:
s = "rw";
break;
case SMI_ACCESS_READ_ONLY:
s = "ro";
break;
case SMI_ACCESS_NOT_ACCESSIBLE:
s = "na";
break;
case SMI_ACCESS_NOTIFY:
s = "no";
break;
default:
break;
}
if (s) fprintf(f, "%s", s);
s = smiRenderType(smiType, SMI_RENDER_NAME | SMI_RENDER_QUALIFIED);
if (s) {
fprintf(f, " %s", s);
free(s);
}
if (smiNode->units) {
fprintf(f, " [%s]", smiNode->units);
} else if (smiType->units) {
fprintf(f, " [%s]", smiNode->units);
}
}
static void
printHeaderTypedefMember(FILE *f, SmiNode *smiNode,
SmiType *smiType, int isIndex, int maxlen, char *name)
{
char *cName, *dNodeName, *dModuleName;
unsigned minSize, maxSize;
SmiModule *smiModule;
smiModule = smiGetNodeModule(smiNode);
cName = translate(name ? name : smiNode->name);
dNodeName = translateUpper(name ? name : smiNode->name);
dModuleName = translateUpper(smiModule ? smiModule->name : "");
switch (smiType->basetype) {
case SMI_BASETYPE_OBJECTIDENTIFIER:
maxSize = smiGetMaxSize(smiType);
minSize = smiGetMinSize(smiType);
if (isIndex && maxSize > 128 - smiNode->oidlen) {
maxSize = 128 - smiNode->oidlen;
}
if (isIndex) {
fprintf(f, " guint32 %s[%u];", cName, maxSize);
fprintf(f, "%*s/* ", maxlen-strlen(cName)+2, "");
printHeaderTypedefMemberComment(f, smiNode, smiType);
fprintf(f, " */\n");
} else {
fprintf(f, " guint32 *%s;", cName);
fprintf(f, "%*s/* ", maxlen-strlen(cName)+5, "");
printHeaderTypedefMemberComment(f, smiNode, smiType);
fprintf(f, " */\n");
}
if (maxSize == minSize) {
fprintf(f,
"#define %s_%sLENGTH %u\n",
dModuleName, dNodeName, maxSize);
} else {
fprintf(f,
"#define %s_%sMINLENGTH %u\n",
dModuleName, dNodeName, minSize);
fprintf(f,
"#define %s_%sMAXLENGTH %u\n",
dModuleName, dNodeName, maxSize);
fprintf(f,
" guint16 _%sLength;\n", cName);
}
break;
case SMI_BASETYPE_OCTETSTRING:
case SMI_BASETYPE_BITS:
maxSize = smiGetMaxSize(smiType);
minSize = smiGetMinSize(smiType);
if (isIndex && maxSize > 128 - smiNode->oidlen) {
maxSize = 128 - smiNode->oidlen;
}
if (isIndex) {
fprintf(f, " guchar %s[%u];", cName, maxSize);
fprintf(f, "%*s/* ", maxlen-strlen(cName)+2, "");
printHeaderTypedefMemberComment(f, smiNode, smiType);
fprintf(f, " */\n");
} else {
fprintf(f, " guchar *%s;", cName);
fprintf(f, "%*s/* ", maxlen-strlen(cName)+5, "");
printHeaderTypedefMemberComment(f, smiNode, smiType);
fprintf(f, " */\n");
}
if (maxSize == minSize) {
fprintf(f,
"#define %s_%sLENGTH %u\n",
dModuleName, dNodeName, maxSize);
} else {
fprintf(f,
"#define %s_%sMINLENGTH %u\n",
dModuleName, dNodeName, minSize);
fprintf(f,
"#define %s_%sMAXLENGTH %u\n",
dModuleName, dNodeName, maxSize);
fprintf(f,
" guint16 _%sLength;\n", cName);
}
break;
case SMI_BASETYPE_ENUM:
case SMI_BASETYPE_INTEGER32:
fprintf(f, " gint32 %s%s;", isIndex ? "" : "*", cName);
fprintf(f, "%*s/* ", maxlen-strlen(cName)+5+isIndex, "");
printHeaderTypedefMemberComment(f, smiNode, smiType);
fprintf(f, " */\n");
break;
case SMI_BASETYPE_UNSIGNED32:
fprintf(f, " guint32 %s%s;", isIndex ? "" : "*", cName);
fprintf(f, "%*s/* ", maxlen-strlen(cName)+5+isIndex, "");
printHeaderTypedefMemberComment(f, smiNode, smiType);
fprintf(f, " */\n");
break;
case SMI_BASETYPE_INTEGER64:
fprintf(f, " gint64 *%s;", cName);
fprintf(f, "%*s/* ", maxlen-strlen(cName)+5, "");
printHeaderTypedefMemberComment(f, smiNode, smiType);
fprintf(f, " */\n");
break;
case SMI_BASETYPE_UNSIGNED64:
fprintf(f, " guint64 *%s;", cName);
fprintf(f, "%*s/* ", maxlen-strlen(cName)+5, "");
printHeaderTypedefMemberComment(f, smiNode, smiType);
fprintf(f, " */\n");
break;
default:
fprintf(f,
" /* ?? */ _%s; \n", cName);
break;
}
xfree(dModuleName);
xfree(dNodeName);
xfree(cName);
}
static void
printHeaderTypedefMemberIndex(FILE *f, SmiNode *smiNode, SmiNode *iNode,
int flags, int maxlen, char *name)
{
SmiType *iType;
iType = smiGetNodeType(iNode);
if (! iType) {
return;
}
printHeaderTypedefMember(f, iNode, iType, 1, maxlen, name);
}
static void
printHeaderTypedef(FILE *f, SmiModule *smiModule, SmiNode *groupNode)
{
SmiNode *smiNode;
SmiType *smiType;
char *cPrefix, *dModuleName, *cGroupName, *dGroupName, *dNodeName;
int writable = 0, count = 0, len = 0;
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
dModuleName = translateUpper(smiModule->name);
cGroupName = translate(groupNode->name);
dGroupName = translateUpper(groupNode->name);
fprintf(f,
"/*\n"
" * C type definitions for %s::%s.\n"
" */\n\n",
smiModule->name, groupNode->name);
for (smiNode = smiGetFirstChildNode(groupNode);
smiNode;
smiNode = smiGetNextChildNode(smiNode)) {
if (smiNode->nodekind & (SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR)
&& (smiNode->access >= SMI_ACCESS_READ_ONLY)) {
if (len < strlen(smiNode->name)) {
len = strlen(smiNode->name);
}
}
}
for (smiNode = smiGetFirstChildNode(groupNode);
smiNode;
smiNode = smiGetNextChildNode(smiNode)) {
if (smiNode->nodekind & (SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR)
&& (smiNode->access >= SMI_ACCESS_READ_ONLY)) {
dNodeName = translateUpper(smiNode->name);
fprintf(f, "#define %s_%-*s (1 << %d) \n", dModuleName, len, dNodeName, count);
xfree(dNodeName);
count++;
}
}
if (count) {
fprintf(f, "\n");
}
fprintf(f, "typedef struct {\n");
foreachIndexDo(f, groupNode, printHeaderTypedefMemberIndex, 0, len);
for (smiNode = smiGetFirstChildNode(groupNode);
smiNode;
smiNode = smiGetNextChildNode(smiNode)) {
if (smiNode->nodekind & (SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR)
&& (smiNode->access >= SMI_ACCESS_READ_ONLY)) {
if (isIndex(groupNode, smiNode)) {
continue;
}
if (smiNode->access == SMI_ACCESS_READ_WRITE) {
writable++;
}
smiType = smiGetNodeType(smiNode);
if (! smiType) {
continue;
}
printHeaderTypedefMember(f, smiNode, smiType, 0, len, 0);
}
}
fprintf(f, "} %s_%s_t;\n\n", cPrefix, cGroupName);
if (groupNode->nodekind == SMI_NODEKIND_ROW) {
char *cTableName;
SmiNode *tableNode;
tableNode = smiGetParentNode(groupNode);
if (tableNode) {
cTableName = translate(tableNode->name);
fprintf(f, "extern void\n"
"%s_get_%s(GNetSnmp *s, %s_%s_t ***%s, gint64 mask);\n\n",
cPrefix, cTableName,
cPrefix, cGroupName, cGroupName);
fprintf(f, "extern void\n"
"%s_free_%s(%s_%s_t **%s);\n\n",
cPrefix, cTableName,
cPrefix, cGroupName, cGroupName);
xfree(cTableName);
}
}
fprintf(f, "extern %s_%s_t *\n"
"%s_new_%s(void);\n\n",
cPrefix, cGroupName, cPrefix, cGroupName);
fprintf(f, "extern void\n"
"%s_get_%s(GNetSnmp *s, %s_%s_t **%s",
cPrefix, cGroupName,
cPrefix, cGroupName,
cGroupName);
if (groupNode->nodekind == SMI_NODEKIND_ROW) {
foreachIndexDo(f, groupNode, printIndexParamsFunc, 1, 0);
}
fprintf(f, ", gint64 mask);\n\n");
if (writable) {
fprintf(f, "extern void\n"
"%s_set_%s(GNetSnmp *s, %s_%s_t *%s, gint64 mask);\n\n",
cPrefix, cGroupName,
cPrefix, cGroupName, cGroupName);
}
fprintf(f, "extern void\n"
"%s_free_%s(%s_%s_t *%s);\n\n",
cPrefix, cGroupName,
cPrefix, cGroupName, cGroupName);
printMethodPrototypes(f, groupNode);
xfree(dGroupName);
xfree(cGroupName);
xfree(dModuleName);
xfree(cPrefix);
}
static void
printHeaderTypedefs(FILE *f, SmiModule *smiModule)
{
SmiNode *smiNode;
int cnt = 0;
const unsigned int groupkind = SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN;
for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
smiNode;
smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
if (isGroup(smiNode, groupkind) && isAccessible(smiNode)) {
cnt++;
printHeaderTypedef(f, smiModule, smiNode);
}
}
if (cnt) {
fprintf(f, "\n");
}
}
static void
dumpHeader(SmiModule *smiModule, char *baseName)
{
char *pModuleName;
FILE *f;
pModuleName = translateUpper(smiModule->name);
f = createFile(baseName, ".h");
if (! f) {
return;
}
fprintTopComment(f, smiModule);
fprintf(f,
"#ifndef _%s_H_\n"
"#define _%s_H_\n"
"\n"
"#include \"gsnmp.h\"\n"
"\n"
"G_BEGIN_DECLS\n"
"\n",
pModuleName, pModuleName);
printHeaderEnumerations(f, smiModule);
printHeaderIdentities(f, smiModule);
printHeaderNotifications(f, smiModule);
printHeaderTypedefs(f, smiModule);
fprintf(f,
"G_END_DECLS\n"
"\n"
"#endif /* _%s_H_ */\n",
pModuleName);
if (fflush(f) || ferror(f)) {
perror("smidump: write error");
exit(1);
}
fclose(f);
xfree(pModuleName);
}
static void
printStubEnumeration(FILE *f, SmiModule *smiModule,
SmiNode *smiNode, SmiType *smiType)
{
SmiNamedNumber *nn;
char *cName, *cPrefix;
char *dName, *dModuleName;
char *name;
int len;
if (smiType && smiType->name) {
name = smiType->name;
} else if (smiNode && smiNode->name) {
name = smiNode->name;
} else {
return;
}
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
dModuleName = translateUpper(smiModule->name);
cName = translate(name);
dName = translateUpper(name);
fprintf(f, "GNetSnmpEnum const %s_enums_%s[] = {\n",
cPrefix, cName);
for (len = 0, nn = smiGetFirstNamedNumber(smiType); nn;
nn = smiGetNextNamedNumber(nn)) {
if (len < strlen(nn->name)) {
len = strlen(nn->name);
}
}
for (nn = smiGetFirstNamedNumber(smiType); nn;
nn = smiGetNextNamedNumber(nn)) {
char *dEnum = translateUpper(nn->name);
fprintf(f, " { %s_%s_%s,%*s \"%s\" },\n",
dModuleName, dName, dEnum,
len - strlen(dEnum), "", nn->name);
xfree(dEnum);
}
fprintf(f,
" { 0, NULL }\n"
"};\n"
"\n");
xfree(dName);
xfree(cName);
xfree(dModuleName);
xfree(cPrefix);
}
static void
printStubEnumerations(FILE *f, SmiModule *smiModule)
{
SmiNode *smiNode, *parentNode;
SmiType *smiType;
int cnt = 0;
const unsigned int groupkind = SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN;
for (smiNode = smiGetFirstNode(smiModule, groupkind);
smiNode;
smiNode = smiGetNextNode(smiNode, groupkind)) {
parentNode = smiGetParentNode(smiNode);
if (! parentNode || ! isGroup(parentNode, groupkind)) {
continue;
}
smiType = smiGetNodeType(smiNode);
if (smiType && !smiType->name
&& smiType->basetype == SMI_BASETYPE_ENUM
&& smiGetTypeModule(smiType) == smiModule) {
cnt++;
printStubEnumeration(f, smiModule, smiNode, smiType);
}
}
for (smiType = smiGetFirstType(smiModule);
smiType;
smiType = smiGetNextType(smiType)) {
if (smiType->basetype == SMI_BASETYPE_ENUM
&& smiGetTypeModule(smiType) == smiModule) {
cnt++;
printStubEnumeration(f, smiModule, NULL, smiType);
}
}
if (cnt) {
fprintf(f, "\n");
}
}
static void
printStubIdentities(FILE *f, SmiModule *smiModule)
{
SmiNode *smiNode, *moduleIdentityNode, *parentNode;
char *cName, *cModuleName;
char *dName, *dModuleName;
int cnt = 0;
moduleIdentityNode = smiGetModuleIdentityNode(smiModule);
cModuleName = translateLower(smiModule->name);
dModuleName = translateUpper(smiModule->name);
for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_NODE);
smiNode;
smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_NODE)) {
parentNode = smiGetParentNode(smiNode);
if (! parentNode || ! isGroup(parentNode, SMI_NODEKIND_NODE)) {
continue;
}
if (smiNode->status == SMI_STATUS_UNKNOWN) {
continue;
}
if (smiNode == moduleIdentityNode) {
continue;
}
cnt++;
cName = translate(smiNode->name);
dName = translateUpper(smiNode->name);
fprintf(f,
"static guint32 const %s[]\n\t= { %s_%s };\n",
cName, dModuleName, dName);
xfree(dName);
xfree(cName);
}
if (cnt) {
fprintf(f,
"\n"
"GNetSnmpIdentity const %s_identities[] = {\n",
cModuleName);
for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_NODE);
smiNode;
smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_NODE)) {
if (smiNode->status == SMI_STATUS_UNKNOWN) {
continue;
}
if (smiNode == moduleIdentityNode) {
continue;
}
cName = translate(smiNode->name);
fprintf(f, " { %s,\n"
" G_N_ELEMENTS(%s),\n"
" \"%s\" },\n",
cName, cName, smiNode->name);
xfree(cName);
}
fprintf(f,
" { 0, 0, NULL }\n"
"};\n"
"\n"
"\n");
}
xfree(dModuleName);
xfree(cModuleName);
}
static void
printStubNotifications(FILE *f, SmiModule *smiModule)
{
SmiNode *smiNode;
char *cName, *cModuleName;
char *dName, *dModuleName;
int cnt = 0;
cModuleName = translateLower(smiModule->name);
dModuleName = translateUpper(smiModule->name);
for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_NOTIFICATION);
smiNode;
smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_NOTIFICATION)) {
if (smiNode->status == SMI_STATUS_UNKNOWN) {
continue;
}
cnt++;
cName = translate(smiNode->name);
dName = translateUpper(smiNode->name);
fprintf(f,
"static guint32 const %s[]\n\t= { %s_%s };\n",
cName, dModuleName, dName);
xfree(dName);
xfree(cName);
}
if (cnt) {
fprintf(f,
"\n"
"GNetSnmpIdentity const %s_notifications[] = {\n",
cModuleName);
for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_NOTIFICATION);
smiNode;
smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_NOTIFICATION)) {
if (smiNode->status == SMI_STATUS_UNKNOWN) {
continue;
}
cName = translate(smiNode->name);
fprintf(f, " { %s,\n"
" G_N_ELEMENTS(%s),\n"
" \"%s\" },\n",
cName, cName, smiNode->name);
xfree(cName);
}
fprintf(f,
" { 0, 0, NULL }\n"
"};\n"
"\n"
"\n");
}
xfree(dModuleName);
xfree(cModuleName);
}
static int
printSizeConstraints(FILE *f, SmiNode *smiNode, SmiType *smiType)
{
SmiRange *smiRange;
unsigned int minSize, maxSize;
int cnt;
char *cName;
cName = translate(smiNode->name);
for (cnt = 0; !cnt && smiType; smiType = smiGetParentType(smiType)) {
for (smiRange = smiGetFirstRange(smiType);
smiRange ; smiRange = smiGetNextRange(smiRange)) {
minSize = smiRange->minValue.value.unsigned32;
maxSize = smiRange->maxValue.value.unsigned32;
if (minSize == 0 && maxSize >= 65535) continue;
if (f) {
if (cnt) {
fprintf(f, ", %u, %u", minSize, maxSize);
} else {
fprintf(f, "static guint16 %s_constraints[] = {%uU, %uU",
cName, minSize, maxSize);
}
}
cnt++;
}
}
xfree(cName);
if (f && cnt) fprintf(f, ", 0, 0};\n");
return (cnt > 0);
}
static int
printInteger32RangeConstraints(FILE *f, SmiNode *smiNode, SmiType *smiType)
{
SmiRange *smiRange;
long minSize, maxSize;
int cnt;
char *cName;
cName = translate(smiNode->name);
for (cnt = 0; !cnt && smiType; smiType = smiGetParentType(smiType)) {
for (smiRange = smiGetFirstRange(smiType);
smiRange ; smiRange = smiGetNextRange(smiRange)) {
minSize = smiRange->minValue.value.integer32;
maxSize = smiRange->maxValue.value.integer32;
if (minSize < -2147483647 && maxSize > 2147483646) continue;
if (f) {
if (cnt) {
fprintf(f, ", %ldL, %ldL", minSize, maxSize);
} else {
fprintf(f, "static gint32 %s_constraints[] = {%ldL, %ldL",
cName, minSize, maxSize);
}
}
cnt++;
}
}
xfree(cName);
if (f && cnt) fprintf(f, ", 0, 0};\n");
return (cnt > 0);
}
static int
printUnsigned32RangeConstraints(FILE *f, SmiNode *smiNode, SmiType *smiType)
{
SmiRange *smiRange;
unsigned long minSize, maxSize;
int cnt;
char *cName;
cName = translate(smiNode->name);
for (cnt = 0; !cnt && smiType; smiType = smiGetParentType(smiType)) {
for (smiRange = smiGetFirstRange(smiType);
smiRange ; smiRange = smiGetNextRange(smiRange)) {
minSize = smiRange->minValue.value.unsigned32;
maxSize = smiRange->maxValue.value.unsigned32;
if (minSize == 0 && maxSize >= 4294967295UL) continue;
if (f) {
if (cnt) {
fprintf(f, ", %luUL, %luUL", minSize, maxSize);
} else {
fprintf(f, "static guint32 %s_constraints[] = {%luUL, %luUL",
cName, minSize, maxSize);
}
}
cnt++;
}
}
xfree(cName);
if (f && cnt) fprintf(f, ", 0, 0};\n");
return (cnt > 0);
}
static int
printConstraints(FILE *f, SmiNode *smiNode, SmiNode *groupNode, int flags)
{
SmiType *smiType;
int cnt;
smiType = smiGetNodeType(smiNode);
if (! smiType) {
return 0;
}
/*
* Generally suppress all INDEX objects (treat them as if they
* were not-accessible). This is a cheap optimization for SMIv1
* MIBs where these objects were generally read-only.
*/
if (flags && isIndex(groupNode, smiNode)) {
return 0;
}
if (smiNode->access == SMI_ACCESS_NOT_ACCESSIBLE
|| smiNode->access == SMI_ACCESS_NOTIFY) {
return 0;
}
switch (smiType->basetype) {
case SMI_BASETYPE_OCTETSTRING:
cnt = printSizeConstraints(f, smiNode, smiType);
break;
case SMI_BASETYPE_INTEGER32:
cnt = printInteger32RangeConstraints(f, smiNode, smiType);
break;
case SMI_BASETYPE_UNSIGNED32:
cnt = printUnsigned32RangeConstraints(f, smiNode, smiType);
break;
default:
cnt = 0;
break;
}
return cnt;
}
static int
printScalarsAttributesContraints(FILE *f, SmiNode *groupNode)
{
SmiNode *smiNode;
int n = 0;
for (smiNode = smiGetFirstChildNode(groupNode);
smiNode;
smiNode = smiGetNextChildNode(smiNode)) {
n += printConstraints(f, smiNode, groupNode, 0);
}
return n;
}
static int
printTableAttributesConstraints(FILE *f, SmiNode *rowNode)
{
SmiNode *smiNode;
int idx, cnt, n = 0;
for (smiNode = smiGetFirstChildNode(rowNode), idx = 0, cnt = 0;
smiNode;
smiNode = smiGetNextChildNode(smiNode)) {
if (isIndex(rowNode, smiNode)) idx++;
cnt++;
}
for (smiNode = smiGetFirstChildNode(rowNode);
smiNode;
smiNode = smiGetNextChildNode(smiNode)) {
n += printConstraints(f, smiNode, rowNode, cnt > idx);
}
return n;
}
static void
printStubContraints(FILE *f, SmiModule *smiModule)
{
SmiNode *smiNode;
int cnt = 0;
const unsigned int groupkind = SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN;
for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
smiNode;
smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
if (isGroup(smiNode, groupkind) && isAccessible(smiNode)) {
if (smiNode->nodekind == SMI_NODEKIND_ROW) {
cnt += printTableAttributesConstraints(f, smiNode);
} else {
cnt += printScalarsAttributesContraints(f, smiNode);
}
}
}
if (cnt) {
fprintf(f, "\n\n");
}
}
static void
printAttribute(FILE *f, SmiNode *smiNode, SmiNode *groupNode, int flags)
{
SmiType *smiType;
char *snmpType;
char *dModuleName, *dNodeName;
char *cPrefix, *cGroupName, *cNodeName;
unsigned maxSize = 0, minSize = 0;
int cnt;
smiType = smiGetNodeType(smiNode);
if (!smiType) {
return;
}
snmpType = getSnmpType(smiType);
if (!snmpType) {
return;
}
/*
* Generally suppress all INDEX objects (treat them as if they
* were not-accessible). This is a cheap optimization for SMIv1
* MIBs where these objects were generally read-only.
*/
if (flags && isIndex(groupNode, smiNode)) {
return;
}
if (smiNode->access == SMI_ACCESS_NOT_ACCESSIBLE
|| smiNode->access == SMI_ACCESS_NOTIFY) {
return;
}
dModuleName = translateUpper(smiGetNodeModule(smiNode)->name);
dNodeName = translateUpper(smiNode->name);
cNodeName = translate(smiNode->name);
cGroupName = translate(groupNode->name);
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiGetNodeModule(smiNode)->name);
fprintf(f,
" { %u, %s,\n"
" %s_%s, \"%s\",\n",
smiNode->oid[smiNode->oidlen-1], snmpType,
dModuleName, dNodeName, smiNode->name);
switch (smiType->basetype) {
case SMI_BASETYPE_OCTETSTRING:
cnt = printSizeConstraints(NULL, smiNode, smiType);
break;
case SMI_BASETYPE_INTEGER32:
cnt = printInteger32RangeConstraints(NULL, smiNode, smiType);
break;
case SMI_BASETYPE_UNSIGNED32:
cnt = printUnsigned32RangeConstraints(NULL, smiNode, smiType);
break;
default:
cnt = 0;
break;
}
if (cnt) {
fprintf(f, " %s_constraints,\n", cNodeName);
} else {
fprintf(f, " NULL,\n");
}
if (! flags && isIndex(groupNode, smiNode)) {
fprintf(f, " -1,\n");
} else {
fprintf(f,
" G_STRUCT_OFFSET(%s_%s_t, %s),\n",
cPrefix, cGroupName, cNodeName);
}
switch (smiType->basetype) {
case SMI_BASETYPE_OCTETSTRING:
case SMI_BASETYPE_BITS:
case SMI_BASETYPE_OBJECTIDENTIFIER:
maxSize = smiGetMaxSize(smiType);
minSize = smiGetMinSize(smiType);
break;
default:
break;
}
if (minSize != maxSize) {
fprintf(f,
" G_STRUCT_OFFSET(%s_%s_t, _%sLength)",
cPrefix, cGroupName, cNodeName);
} else {
fprintf(f,
" 0");
}
fprintf(f,
",\n"
" %s },\n",
(smiNode->access > SMI_ACCESS_READ_ONLY) ? "GSNMP_ATTR_FLAG_WRITABLE" : "0");
xfree(cPrefix);
xfree(cGroupName);
xfree(cNodeName);
xfree(dNodeName);
xfree(dModuleName);
}
static void
printScalarsAttributes(FILE *f, SmiModule *smiModule, SmiNode *groupNode)
{
SmiNode *smiNode;
for (smiNode = smiGetFirstChildNode(groupNode);
smiNode;
smiNode = smiGetNextChildNode(smiNode)) {
printAttribute(f, smiNode, groupNode, 0);
}
}
static void
printTableAttributes(FILE *f, SmiModule *smiModule, SmiNode *rowNode)
{
SmiNode *smiNode;
int idx, cnt;
for (smiNode = smiGetFirstChildNode(rowNode), idx = 0, cnt = 0;
smiNode;
smiNode = smiGetNextChildNode(smiNode)) {
if (isIndex(rowNode, smiNode)) idx++;
cnt++;
}
for (smiNode = smiGetFirstChildNode(rowNode);
smiNode;
smiNode = smiGetNextChildNode(smiNode)) {
printAttribute(f, smiNode, rowNode, cnt > idx);
}
}
static void
printStubAttributes(FILE *f, SmiModule *smiModule)
{
SmiNode *smiNode;
char *cName;
int cnt = 0;
unsigned int i;
const unsigned int groupkind = SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN;
for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
smiNode;
smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
if (isGroup(smiNode, groupkind) && isAccessible(smiNode)) {
cnt++;
cName = translate(smiNode->name);
fprintf(f, "static guint32 const %s_oid[] = {", cName);
for (i = 0; i < smiNode->oidlen; i++) {
fprintf(f, "%s%u", i ? ", " : "", smiNode->oid[i]);
}
fprintf(f, "};\n\n");
fprintf(f,
"static GNetSnmpAttribute %s_attr[] = {\n",
cName);
if (smiNode->nodekind == SMI_NODEKIND_ROW) {
printTableAttributes(f, smiModule, smiNode);
} else {
printScalarsAttributes(f, smiModule, smiNode);
}
fprintf(f,
" { 0, 0, 0, NULL }\n"
"};\n"
"\n");
xfree(cName);
}
}
if (cnt) {
fprintf(f, "\n");
}
}
static void
printInteger32RangeChecks(FILE *f, char *cGroupName, char *cName,
SmiType *smiType)
{
SmiRange *smiRange;
long int minSize, maxSize;
int c;
for (c = 0; smiType; smiType = smiGetParentType(smiType)) {
for (smiRange = smiGetFirstRange(smiType);
smiRange ; smiRange = smiGetNextRange(smiRange)) {
minSize = smiRange->minValue.value.integer32;
maxSize = smiRange->maxValue.value.integer32;
if (! c) {
fprintf(f, " if (");
} else {
fprintf(f, "\n && ");
}
if (minSize == -2147483647 - 1) {
fprintf(f, "(%s->%s > %ld)", cGroupName, cName, maxSize);
} else if (maxSize == 2147483647) {
fprintf(f, "(%s->%s < %ld)", cGroupName, cName, minSize);
} else if (minSize == maxSize) {
fprintf(f, "(%s->%s != %ld)", cGroupName, cName, maxSize);
} else {
fprintf(f, "(%s->%s < %ld || %s->%s > %ld)",
cGroupName, cName, minSize,
cGroupName, cName, maxSize);
}
c++;
}
}
if (c) {
fprintf(f, ") {\n"
" return -1;\n"
" }\n");
}
}
static void
printUnsigned32RangeChecks(FILE *f, char *cGroupName, char *cName,
SmiType *smiType)
{
SmiRange *smiRange;
unsigned long minSize, maxSize;
int c;
for (c = 0; smiType; smiType = smiGetParentType(smiType)) {
for (smiRange = smiGetFirstRange(smiType);
smiRange ; smiRange = smiGetNextRange(smiRange)) {
minSize = smiRange->minValue.value.unsigned32;
maxSize = smiRange->maxValue.value.unsigned32;
if (minSize == 0 && maxSize == 4294967295U) {
continue;
}
if (! c) {
fprintf(f, " if (");
} else {
fprintf(f, "\n && ");
}
if (minSize == 0) {
fprintf(f, "(%s->%s > %lu)", cGroupName, cName, maxSize);
} else if (maxSize == 4294967295U) {
fprintf(f, "(%s->%s < %lu)", cGroupName, cName, minSize);
} else if (minSize == maxSize) {
fprintf(f, "(%s->%s != %lu)", cGroupName, cName, maxSize);
} else {
fprintf(f, "(%s->%s < %lu || %s->%s > %lu)",
cGroupName, cName, minSize,
cGroupName, cName, maxSize);
}
c++;
}
}
if (c) {
fprintf(f, ") {\n"
" return -1;\n"
" }\n");
}
}
static void
printUnpackMethod(FILE *f, SmiModule *smiModule, SmiNode *groupNode)
{
SmiElement *smiElement;
SmiNode *indexNode = NULL;
SmiNode *iNode;
SmiType *iType;
char *cPrefix, *cGroupName, *cName, *name;
unsigned maxSize, minSize;
int last = 0;
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
cGroupName = translate(groupNode->name);
switch (groupNode->indexkind) {
case SMI_INDEX_INDEX:
case SMI_INDEX_REORDER:
indexNode = groupNode;
break;
case SMI_INDEX_EXPAND: /* TODO: we have to do more work here! */
indexNode = NULL;
break;
case SMI_INDEX_AUGMENT:
case SMI_INDEX_SPARSE:
indexNode = smiGetRelatedNode(groupNode);
break;
case SMI_INDEX_UNKNOWN:
indexNode = NULL;
break;
}
/*
* First check if there are OID or string types so that we
* know whether we need some additional variables.
*/
for (smiElement = smiGetFirstElement(indexNode);
smiElement; smiElement = smiGetNextElement(smiElement)) {
iNode = smiGetElementNode(smiElement);
if (iNode) {
iType = smiGetNodeType(iNode);
if (iType
&& (iType->basetype == SMI_BASETYPE_OCTETSTRING
|| iType->basetype == SMI_BASETYPE_OBJECTIDENTIFIER)) {
break;
}
}
}
fprintf(f,
"static inline int\n"
"unpack_%s(GNetSnmpVarBind *vb, %s_%s_t *%s)\n"
"{\n"
" guint8 idx = %u;\n"
"%s"
"\n",
cGroupName, cPrefix, cGroupName, cGroupName,
groupNode->oidlen + 1,
smiElement ? " guint16 i, len;\n" : "");
for (smiElement = smiGetFirstElement(indexNode);
smiElement; smiElement = smiGetNextElement(smiElement)) {
iNode = smiGetElementNode(smiElement);
last = (smiGetNextElement(smiElement) == NULL);
if (iNode) {
iType = smiGetNodeType(iNode);
if (! iType) {
continue;
}
name = getIndexName(indexNode, iNode, smiElement);
cName = translate(name ? name : iNode->name);
switch (iType->basetype) {
case SMI_BASETYPE_ENUM:
case SMI_BASETYPE_INTEGER32:
fprintf(f,
" if (vb->oid_len < idx) return -1;\n"
" %s->%s = vb->oid[idx++];\n",
cGroupName, cName);
printInteger32RangeChecks(f, cGroupName, cName, iType);
break;
case SMI_BASETYPE_UNSIGNED32:
fprintf(f,
" if (vb->oid_len < idx) return -1;\n"
" %s->%s = vb->oid[idx++];\n",
cGroupName, cName);
printUnsigned32RangeChecks(f, cGroupName, cName, iType);
break;
case SMI_BASETYPE_OCTETSTRING:
maxSize = smiGetMaxSize(iType);
minSize = smiGetMinSize(iType);
if (maxSize > 128 - iNode->oidlen) {
maxSize = 128 - iNode->oidlen;
}
if (minSize == maxSize) {
fprintf(f,
" len = %u;\n",
minSize);
} else if (last && indexNode->implied) {
fprintf(f,
" if (vb->oid_len < idx) return -1;\n"
" len = vb->oid_len - idx;\n");
} else {
fprintf(f,
" if (vb->oid_len < idx) return -1;\n"
" len = vb->oid[idx++];\n");
}
if (minSize != maxSize) {
if (minSize > 0 && maxSize < 65535) {
fprintf(f,
" if (len < %u || len > %u) return -1;\n",
minSize, maxSize);
} else if (minSize > 0 && maxSize == 65535) {
fprintf(f,
" if (len < %u) return -1;\n", minSize);
} else if (minSize == 0 && maxSize < 65535) {
fprintf(f,
" if (len > %u) return -1;\n", maxSize);
}
}
fprintf(f,
" if (vb->oid_len < idx + len) return -1;\n"
" for (i = 0; i < len; i++) {\n"
" %s->%s[i] = vb->oid[idx++];\n"
" }\n",
cGroupName, cName);
if (minSize != maxSize) {
fprintf(f,
" %s->_%sLength = len;\n", cGroupName, cName);
}
break;
case SMI_BASETYPE_OBJECTIDENTIFIER:
maxSize = smiGetMaxSize(iType);
minSize = smiGetMinSize(iType);
if (maxSize > 128 - iNode->oidlen) {
maxSize = 128 - iNode->oidlen;
}
if (minSize == maxSize) {
fprintf(f,
" len = %u;\n"
" if (vb->oid_len < idx + len) return -1;\n",
minSize);
} else if (last && indexNode->implied) {
fprintf(f,
" if (vb->oid_len < idx) return -1;\n"
" len = vb->oid_len - idx;\n");
} else {
fprintf(f,
" if (vb->oid_len < idx) return -1;\n"
" len = vb->oid[idx++];\n"
" if (vb->oid_len < idx + len) return -1;\n");
}
if (minSize != maxSize) {
if (minSize > 0 && maxSize < 65535) {
fprintf(f,
" if (len < %u || len > %u) return -1;\n",
minSize, maxSize);
} else if (minSize > 0 && maxSize == 65535) {
fprintf(f,
" if (len < %u) return -1;\n", minSize);
} else if (minSize == 0 && maxSize < 65535) {
fprintf(f,
" if (len > %u) return -1;\n", maxSize);
}
}
fprintf(f,
" for (i = 0; i < len; i++) {\n"
" %s->%s[i] = vb->oid[idx++];\n"
" }\n",
cGroupName, cName);
if (minSize != maxSize) {
fprintf(f,
" %s->_%sLength = len;\n", cGroupName, cName);
}
break;
default:
fprintf(f,
" /* XXX how to unpack %s->%s ? */\n",
cGroupName, cName);
break;
}
xfree(cName);
if (name) xfree(name);
}
}
fprintf(f,
" if (vb->oid_len > idx) return -1;\n"
" return 0;\n"
"}\n\n");
xfree(cGroupName);
xfree(cPrefix);
}
static void
printPackMethod(FILE *f, SmiModule *smiModule, SmiNode *groupNode)
{
SmiElement *smiElement;
SmiNode *indexNode = NULL;
SmiNode *iNode;
SmiType *iType;
char *cGroupName, *cName, *name;
unsigned maxSize, minSize;
int last = 0;
cGroupName = translate(groupNode->name);
switch (groupNode->indexkind) {
case SMI_INDEX_INDEX:
case SMI_INDEX_REORDER:
indexNode = groupNode;
break;
case SMI_INDEX_EXPAND: /* TODO: we have to do more work here! */
indexNode = NULL;
break;
case SMI_INDEX_AUGMENT:
case SMI_INDEX_SPARSE:
indexNode = smiGetRelatedNode(groupNode);
break;
case SMI_INDEX_UNKNOWN:
indexNode = NULL;
break;
}
/*
* First check if there are OID or string types so that we
* know whether we need some additional variables.
*/
for (smiElement = smiGetFirstElement(indexNode);
smiElement; smiElement = smiGetNextElement(smiElement)) {
iNode = smiGetElementNode(smiElement);
if (iNode) {
iType = smiGetNodeType(iNode);
if (iType
&& (iType->basetype == SMI_BASETYPE_OCTETSTRING
|| iType->basetype == SMI_BASETYPE_OBJECTIDENTIFIER)) {
break;
}
}
}
fprintf(f,
"static inline gint8\n"
"pack_%s(guint32 *base",
cGroupName);
foreachIndexDo(f, groupNode, printIndexParamsFunc, 1, 0);
fprintf(f,
")\n"
"{\n"
" guint8 idx = %u;\n"
"%s"
"\n",
groupNode->oidlen + 1,
smiElement ? " guint16 i, len;\n" : "");
for (smiElement = smiGetFirstElement(indexNode);
smiElement; smiElement = smiGetNextElement(smiElement)) {
iNode = smiGetElementNode(smiElement);
last = (smiGetNextElement(smiElement) == NULL);
if (iNode) {
iType = smiGetNodeType(iNode);
if (! iType) {
continue;
}
name = getIndexName(indexNode, iNode, smiElement);
cName = translate(name ? name : iNode->name);
switch (iType->basetype) {
case SMI_BASETYPE_ENUM:
case SMI_BASETYPE_INTEGER32:
fprintf(f,
" base[idx++] = %s;\n",
cName);
break;
case SMI_BASETYPE_UNSIGNED32:
fprintf(f,
" base[idx++] = %s;\n",
cName);
break;
case SMI_BASETYPE_OCTETSTRING:
maxSize = smiGetMaxSize(iType);
minSize = smiGetMinSize(iType);
if (maxSize > 128 - iNode->oidlen) {
maxSize = 128 - iNode->oidlen;
}
if (minSize == maxSize) {
fprintf(f,
" len = %u;\n",
minSize);
} else if (last && indexNode->implied) {
fprintf(f,
" len = _%sLength;\n",
cName);
} else {
fprintf(f,
" len = _%sLength;\n"
" base[idx++] = len;\n",
cName);
}
if (minSize == maxSize) {
fprintf(f,
" if (len != %u) return -1;\n",
minSize);
} else {
if (minSize > 0 && maxSize < 65535) {
fprintf(f,
" if (len < %u || len > %u) return -1;\n",
minSize, maxSize);
} else if (minSize > 0 && maxSize == 65535) {
fprintf(f,
" if (len < %u) return -1;\n", minSize);
} else if (minSize == 0 && maxSize < 65535) {
fprintf(f,
" if (len > %u) return -1;\n", maxSize);
}
}
fprintf(f,
" for (i = 0; i < len; i++) {\n"
" base[idx++] = %s[i];\n"
" if (idx >= 128) return -1;\n"
" }\n",
cName);
break;
case SMI_BASETYPE_OBJECTIDENTIFIER:
maxSize = smiGetMaxSize(iType);
minSize = smiGetMinSize(iType);
if (maxSize > 128 - iNode->oidlen) {
maxSize = 128 - iNode->oidlen;
}
if (minSize == maxSize) {
fprintf(f,
" len = %u;\n",
minSize);
} else if (last && indexNode->implied) {
fprintf(f,
" len = _%sLength;\n",
cName);
} else {
fprintf(f,
" len = _%sLength;\n"
" base[idx++] = len;\n",
cName);
}
if (minSize == maxSize) {
fprintf(f,
" if (len != %u) return -1;\n",
minSize);
} else {
if (minSize > 0 && maxSize < 65535) {
fprintf(f,
" if (len < %u || len > %u) return -1;\n",
minSize, maxSize);
} else if (minSize > 0 && maxSize == 65535) {
fprintf(f,
" if (len < %u) return -1;\n", minSize);
} else if (minSize == 0 && maxSize < 65535) {
fprintf(f,
" if (len > %u) return -1;\n", maxSize);
}
}
fprintf(f,
" for (i = 0; i < len; i++) {\n"
" base[idx++] = %s[i];\n"
" if (idx >= 128) return -1;\n"
" }\n",
cName);
break;
default:
fprintf(f,
" /* XXX how to pack %s ? */\n", cGroupName);
break;
}
xfree(cName);
if (name) xfree(name);
}
}
fprintf(f,
" return idx;\n"
"}\n\n");
xfree(cGroupName);
}
static void
printAssignMethod(FILE *f, SmiModule *smiModule, SmiNode *groupNode)
{
char *cPrefix, *cGroupName;
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
cGroupName = translate(groupNode->name);
if (groupNode->nodekind == SMI_NODEKIND_ROW) {
printUnpackMethod(f, smiModule, groupNode);
printPackMethod(f, smiModule, groupNode);
}
fprintf(f,
"static inline %s_%s_t *\n"
"assign_%s(GList *vbl)\n"
"{\n"
" %s_%s_t *%s;\n"
" char *p;\n"
"\n",
cPrefix, cGroupName, cGroupName,
cPrefix, cGroupName, cGroupName);
fprintf(f,
" %s = %s_new_%s();\n"
" p = (char *) %s + sizeof(%s_%s_t);\n"
" * (GList **) p = vbl;\n"
"\n",
cGroupName, cPrefix, cGroupName,
cGroupName, cPrefix, cGroupName);
if (groupNode->nodekind == SMI_NODEKIND_ROW) {
fprintf(f,
" if (unpack_%s((GNetSnmpVarBind *) vbl->data, %s) < 0) {\n"
" g_warning(\"%%s: invalid instance identifier\", \"%s\");\n"
" g_free(%s);\n"
" return NULL;\n"
" }\n\n",
cGroupName, cGroupName, cGroupName, cGroupName);
}
fprintf(f,
" gnet_snmp_attr_assign(vbl, %s_oid, G_N_ELEMENTS(%s_oid),\n"
" %s_attr, %s);\n"
"\n"
" return %s;\n"
"}\n"
"\n", cGroupName, cGroupName, cGroupName, cGroupName, cGroupName);
xfree(cGroupName);
xfree(cPrefix);
}
static void
printGetTableMethod(FILE *f, SmiModule *smiModule, SmiNode *rowNode)
{
SmiNode *tableNode;
char *cPrefix, *cModuleName, *cRowName, *cTableName;
unsigned int i;
tableNode = smiGetParentNode(rowNode);
if (! tableNode) {
return;
}
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
cModuleName = translateLower(smiModule->name);
cRowName = translate(rowNode->name);
cTableName = translate(tableNode->name);
fprintf(f,
"void\n"
"%s_get_%s(GNetSnmp *s, %s_%s_t ***%s, gint64 mask)\n"
"{\n"
" GList *in = NULL, *out = NULL;\n",
cPrefix, cTableName, cPrefix, cRowName, cRowName);
fprintf(f,
" GList *row;\n"
" int i;\n");
fprintf(f, " static guint32 const _base[] = {");
for (i = 0; i < rowNode->oidlen; i++) {
fprintf(f, "%u, ", rowNode->oid[i]);
}
fprintf(f, "0};\n");
fprintf(f, " guint32 base[128];\n");
fprintf(f,
"\n"
" *%s = NULL;\n"
" memcpy(base, _base, sizeof(_base));\n"
"\n",
cRowName);
fprintf(f,
" gnet_snmp_attr_get(s, &in, base, %u, %u, %s_attr, mask);\n",
rowNode->oidlen+1, rowNode->oidlen, cRowName);
fprintf(f,
"\n"
" out = gnet_snmp_sync_table(s, in);\n"
" /* gnet_snmp_varbind_list_free(in); */\n"
"\n");
fprintf(f,
" if (out) {\n"
" *%s = (%s_%s_t **) g_malloc0((g_list_length(out) + 1) * sizeof(%s_%s_t *));\n"
" for (row = out, i = 0; row; row = g_list_next(row), i++) {\n"
" (*%s)[i] = assign_%s(row->data);\n"
" }\n"
" }\n"
"}\n"
"\n",
cRowName, cPrefix, cRowName,
cPrefix, cRowName,
cRowName, cRowName);
xfree(cTableName);
xfree(cRowName);
xfree(cModuleName);
xfree(cPrefix);
}
static void
printGetRowMethod(FILE *f, SmiModule *smiModule, SmiNode *rowNode)
{
char *cPrefix, *cRowName;
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
cRowName = translate(rowNode->name);
fprintf(f,
"void\n"
"%s_get_%s(GNetSnmp *s, %s_%s_t **%s",
cPrefix, cRowName, cPrefix, cRowName, cRowName);
foreachIndexDo(f, rowNode, printIndexParamsFunc, 1, 0);
fprintf(f,
", gint64 mask)\n"
"{\n"
" GList *in = NULL, *out = NULL;\n");
fprintf(f,
" guint32 base[128];\n"
" gint8 len;\n"
"\n"
" memcpy(base, %s_oid, sizeof(%s_oid));\n",
cRowName, cRowName);
fprintf(f,
" len = pack_%s(base",
cRowName);
foreachIndexDo(f, rowNode, printIndexParamsFunc, 0, 0);
fprintf(f,
");\n"
" if (len < 0) {\n"
" g_warning(\"%%s: invalid index values\", \"%s\");\n"
" s->error_status = GNET_SNMP_PDU_ERR_INTERNAL;\n"
" return;\n"
" }\n",
cRowName);
fprintf(f,
"\n"
" *%s = NULL;\n"
"\n",
cRowName);
fprintf(f,
" gnet_snmp_attr_get(s, &in, base, len, %u, %s_attr, mask);\n",
rowNode->oidlen, cRowName);
fprintf(f,
"\n"
" out = gnet_snmp_sync_get(s, in);\n"
" g_list_foreach(in, (GFunc) gnet_snmp_varbind_delete, NULL);\n"
" g_list_free(in);\n"
" if (out) {\n"
" if (s->error_status != GNET_SNMP_PDU_ERR_NOERROR) {\n"
" g_list_foreach(out, (GFunc) gnet_snmp_varbind_delete, NULL);\n"
" g_list_free(out);\n"
" return;\n"
" }\n"
" *%s = assign_%s(out);\n"
" }\n"
"}\n"
"\n", cRowName, cRowName);
xfree(cRowName);
xfree(cPrefix);
}
static void
printSetRowMethod(FILE *f, SmiModule *smiModule, SmiNode *rowNode)
{
char *cPrefix, *cRowName, *cTableName;
SmiNode *tableNode;
tableNode = smiGetParentNode(rowNode);
if (! tableNode) {
return;
}
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
cRowName = translate(rowNode->name);
cTableName = translate(tableNode->name);
fprintf(f,
"void\n"
"%s_set_%s(GNetSnmp *s, %s_%s_t *%s, gint64 mask)\n"
"{\n"
" GList *in = NULL, *out = NULL;\n",
cPrefix, cRowName, cPrefix, cRowName, cRowName);
fprintf(f,
" guint32 base[128];\n"
" gint8 len;\n"
"\n"
" memcpy(base, %s_oid, sizeof(%s_oid));\n",
cRowName, cRowName);
fprintf(f,
" len = pack_%s(base", cRowName);
foreachIndexDo(f, rowNode, printIndexParamsPassFunc, 0, 0);
fprintf(f,
");\n"
" if (len < 0) {\n"
" g_warning(\"%%s: invalid index values\", \"%s\");\n"
" s->error_status = GNET_SNMP_PDU_ERR_INTERNAL;\n"
" return;\n"
" }\n"
"\n",
cRowName);
fprintf(f,
" gnet_snmp_attr_set(s, &in, base, len, %u, %s_attr, mask, %s);\n",
rowNode->oidlen, cRowName, cRowName);
fprintf(f,
"\n"
" out = gnet_snmp_sync_set(s, in);\n"
" g_list_foreach(in, (GFunc) gnet_snmp_varbind_delete, NULL);\n"
" g_list_free(in);\n"
" if (out) {\n"
" g_list_foreach(out, (GFunc) gnet_snmp_varbind_delete, NULL);\n"
" g_list_free(out);\n"
" }\n"
"}\n"
"\n");
xfree(cTableName);
xfree(cRowName);
xfree(cPrefix);
}
static void
printCreateMethod(FILE *f, SmiNode *groupNode, SmiNode *smiNode)
{
char *cPrefix, *cNodeName, *cGroupName;
char *dModuleName, *dNodeName;
SmiModule *smiModule;
smiModule = smiGetNodeModule(smiNode);
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
dModuleName = translateUpper(smiModule->name);
cGroupName = translate(groupNode->name);
cNodeName = translate(smiNode->name);
dNodeName = translateUpper(smiNode->name);
fprintf(f,
"void\n"
"%s_create_%s(GNetSnmp *s",
cPrefix, cGroupName);
foreachIndexDo(f, groupNode, printIndexParamsFunc, 1, 0);
fprintf(f,
")\n"
"{\n"
" %s_%s_t *%s;\n"
" gint32 create = 4; /* SNMPv2-TC::RowStatus createAndGo */\n"
"\n",
cPrefix, cGroupName, cGroupName);
fprintf(f,
" %s = %s_new_%s();\n",
cGroupName, cPrefix, cGroupName);
foreachIndexDo(f, groupNode, printIndexAssignmentFunc, 0, 0);
fprintf(f, " %s->%s = &create;\n",
cGroupName, cNodeName);
fprintf(f,
" %s_set_%s(s, %s, %s_%s);\n"
" %s_free_%s(%s);\n",
cPrefix, cGroupName, cGroupName,
dModuleName, dNodeName,
cPrefix, cGroupName, cGroupName);
fprintf(f,
"}\n"
"\n");
xfree(dNodeName);
xfree(cNodeName);
xfree(cGroupName);
xfree(dModuleName);
xfree(cPrefix);
}
static void
printDeleteMethod(FILE *f, SmiNode *groupNode, SmiNode *smiNode)
{
char *cPrefix, *cNodeName, *cGroupName;
char *dModuleName, *dNodeName;
SmiModule *smiModule;
smiModule = smiGetNodeModule(smiNode);
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
dModuleName = translateUpper(smiModule->name);
cGroupName = translate(groupNode->name);
cNodeName = translate(smiNode->name);
dNodeName = translateUpper(smiNode->name);
fprintf(f,
"void\n"
"%s_delete_%s(GNetSnmp *s",
cPrefix, cGroupName);
foreachIndexDo(f, groupNode, printIndexParamsFunc, 1, 0);
fprintf(f,
")\n"
"{\n"
" %s_%s_t *%s;\n"
" gint32 destroy = 6; /* SNMPv2-TC::RowStatus destroy */\n"
"\n",
cPrefix, cGroupName, cGroupName);
fprintf(f,
" %s_get_%s(s, &%s",
cPrefix, cGroupName, cGroupName);
foreachIndexDo(f, groupNode, printIndexParamsFunc, 0, 0);
fprintf(f,
", %s_%s);\n"
" if (s->error_status || !%s) return;\n",
dModuleName, dNodeName,
cGroupName);
fprintf(f, " %s->%s = &destroy;\n",
cGroupName, cNodeName);
fprintf(f,
" %s_set_%s(s, %s, %s_%s);\n"
" %s_free_%s(%s);\n",
cPrefix, cGroupName, cGroupName,
dModuleName, dNodeName,
cPrefix, cGroupName, cGroupName);
fprintf(f,
"}\n"
"\n");
xfree(dNodeName);
xfree(cNodeName);
xfree(cGroupName);
xfree(dModuleName);
xfree(cPrefix);
}
static void
printSetMethod(FILE *f, SmiNode *groupNode, SmiNode *smiNode)
{
char *cPrefix, *cNodeName, *cGroupName;
char *dModuleName, *dNodeName;
SmiType *smiType;
SmiModule *smiModule;
unsigned minSize, maxSize;
smiModule = smiGetNodeModule(smiNode);
smiType = smiGetNodeType(smiNode);
if (! smiType) {
return;
}
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
dModuleName = translateUpper(smiModule->name);
cGroupName = translate(groupNode->name);
cNodeName = translate(smiNode->name);
dNodeName = translateUpper(smiNode->name);
fprintf(f,
"void\n"
"%s_set_%s(GNetSnmp *s",
cPrefix, cNodeName);
foreachIndexDo(f, groupNode, printIndexParamsFunc, 1, 0);
printParam(f, smiNode);
fprintf(f,
")\n"
"{\n"
" %s_%s_t *%s;\n"
"\n", cPrefix, cGroupName, cGroupName);
fprintf(f,
" %s_get_%s(s, &%s",
cPrefix, cGroupName, cGroupName);
foreachIndexDo(f, groupNode, printIndexParamsFunc, 0, 0);
fprintf(f,
", %s_%s);\n"
" if (s->error_status || !%s) return;\n",
dModuleName, dNodeName,
cGroupName);
switch (smiType->basetype) {
case SMI_BASETYPE_OBJECTIDENTIFIER:
case SMI_BASETYPE_OCTETSTRING:
maxSize = smiGetMaxSize(smiType);
minSize = smiGetMinSize(smiType);
fprintf(f, " %s->%s = %s;\n",
cGroupName, cNodeName, cNodeName);
if (minSize != maxSize) {
fprintf(f, " %s->_%sLength = _%sLength;\n",
cGroupName, cNodeName, cNodeName);
}
break;
case SMI_BASETYPE_UNSIGNED32:
case SMI_BASETYPE_ENUM:
case SMI_BASETYPE_INTEGER32:
fprintf(f, " %s->%s = &%s;\n",
cGroupName, cNodeName, cNodeName);
break;
default:
fprintf(f, " /* ?? */\n");
break;
}
fprintf(f,
" %s_set_%s(s, %s, %s_%s);\n"
" %s_free_%s(%s);\n",
cPrefix, cGroupName, cGroupName,
dModuleName, dNodeName,
cPrefix, cGroupName, cGroupName);
fprintf(f,
"}\n"
"\n");
xfree(dNodeName);
xfree(cNodeName);
xfree(cGroupName);
xfree(dModuleName);
xfree(cPrefix);
}
static void
printGetScalarsMethod(FILE *f, SmiModule *smiModule, SmiNode *groupNode)
{
char *cPrefix, *cGroupName;
unsigned int i;
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
cGroupName = translate(groupNode->name);
fprintf(f,
"void\n"
"%s_get_%s(GNetSnmp *s, %s_%s_t **%s, gint64 mask)\n"
"{\n"
" GList *in = NULL, *out = NULL;\n",
cPrefix, cGroupName, cPrefix, cGroupName, cGroupName);
fprintf(f, " static const guint32 _base[] = {");
for (i = 0; i < groupNode->oidlen; i++) {
fprintf(f, "%u, ", groupNode->oid[i]);
}
fprintf(f, "0};\n");
fprintf(f, " guint32 base[128];\n");
fprintf(f,
"\n"
" *%s = NULL;\n"
" memcpy(base, _base, sizeof(_base));\n"
"\n",
cGroupName);
fprintf(f,
" gnet_snmp_attr_get(s, &in, base, %u, %u, %s_attr, mask);\n",
groupNode->oidlen + 1, groupNode->oidlen, cGroupName);
fprintf(f,
"\n"
" out = gnet_snmp_sync_getnext(s, in);\n"
" g_list_foreach(in, (GFunc) gnet_snmp_varbind_delete, NULL);\n"
" g_list_free(in);\n"
" if (out) {\n"
" if (s->error_status != GNET_SNMP_PDU_ERR_NOERROR) {\n"
" g_list_foreach(out, (GFunc) gnet_snmp_varbind_delete, NULL);\n"
" g_list_free(out);\n"
" return;\n"
" }\n"
" *%s = assign_%s(out);\n"
" }\n"
"}\n"
"\n", cGroupName, cGroupName);
xfree(cGroupName);
xfree(cPrefix);
}
static void
printSetScalarsMethod(FILE *f, SmiModule *smiModule, SmiNode *groupNode)
{
char *cPrefix, *cGroupName;
unsigned int i;
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
cGroupName = translate(groupNode->name);
fprintf(f,
"void\n"
"%s_set_%s(GNetSnmp *s, %s_%s_t *%s, gint64 mask)\n"
"{\n"
" GList *in = NULL, *out = NULL;\n",
cPrefix, cGroupName, cPrefix, cGroupName, cGroupName);
fprintf(f, " static guint32 base[] = {");
for (i = 0; i < groupNode->oidlen; i++) {
fprintf(f, "%u, ", groupNode->oid[i]);
}
fprintf(f, "0, 0};\n\n");
fprintf(f,
" gnet_snmp_attr_set(s, &in, base, %u, %u, %s_attr, mask, %s);\n",
groupNode->oidlen + 2, groupNode->oidlen, cGroupName, cGroupName);
fprintf(f,
"\n"
" out = gnet_snmp_sync_set(s, in);\n"
" g_list_foreach(in, (GFunc) gnet_snmp_varbind_delete, NULL);\n"
" g_list_free(in);\n"
" if (out) {\n"
" g_list_foreach(out, (GFunc) gnet_snmp_varbind_delete, NULL);\n"
" g_list_free(out);\n"
" }\n"
"}\n"
"\n");
xfree(cGroupName);
xfree(cPrefix);
}
static void
printNewMethod(FILE *f, SmiModule *smiModule, SmiNode *groupNode)
{
char *cPrefix, *cGroupName;
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
cGroupName = translate(groupNode->name);
fprintf(f,
"%s_%s_t *\n"
"%s_new_%s()\n"
"{\n"
" %s_%s_t *%s;\n"
"\n",
cPrefix, cGroupName,
cPrefix, cGroupName,
cPrefix, cGroupName, cGroupName);
fprintf(f,
" %s = (%s_%s_t *) g_malloc0(sizeof(%s_%s_t) + sizeof(gpointer));\n"
" return %s;\n"
"}\n"
"\n",
cGroupName, cPrefix, cGroupName,
cPrefix, cGroupName, cGroupName);
xfree(cGroupName);
xfree(cPrefix);
}
static void
printFreeTableMethod(FILE *f, SmiModule *smiModule, SmiNode *groupNode)
{
SmiNode *tableNode;
char *cPrefix, *cGroupName, *cTableName;
tableNode = smiGetParentNode(groupNode);
if (! tableNode) {
return;
}
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
cGroupName = translate(groupNode->name);
cTableName = translate(tableNode->name);
fprintf(f,
"void\n"
"%s_free_%s(%s_%s_t **%s)\n"
"{\n"
" int i;\n"
"\n",
cPrefix, cTableName, cPrefix, cGroupName, cGroupName);
fprintf(f,
" if (%s) {\n"
" for (i = 0; %s[i]; i++) {\n"
" %s_free_%s(%s[i]);\n"
" }\n"
" g_free(%s);\n"
" }\n"
"}\n"
"\n",
cGroupName, cGroupName, cPrefix,
cGroupName, cGroupName, cGroupName);
xfree(cTableName);
xfree(cGroupName);
xfree(cPrefix);
}
static void
printFreeMethod(FILE *f, SmiModule *smiModule, SmiNode *groupNode)
{
char *cPrefix, *cGroupName;
cPrefix = prefix ? xstrdup(prefix) : translateLower(smiModule->name);
cGroupName = translate(groupNode->name);
fprintf(f,
"void\n"
"%s_free_%s(%s_%s_t *%s)\n"
"{\n"
" GList *vbl;\n"
" char *p;\n"
"\n",
cPrefix, cGroupName, cPrefix, cGroupName, cGroupName);
fprintf(f,
" if (%s) {\n"
" p = (char *) %s + sizeof(%s_%s_t);\n"
" vbl = * (GList **) p;\n"
" g_list_foreach(vbl, (GFunc) gnet_snmp_varbind_delete, NULL);\n"
" g_list_free(vbl);\n"
" g_free(%s);\n"
" }\n"
"}\n"
"\n",
cGroupName, cGroupName, cPrefix, cGroupName, cGroupName);
xfree(cGroupName);
xfree(cPrefix);
}
static void
printStubMethod2(FILE *f, SmiNode *groupNode)
{
SmiNode *smiNode;
SmiType *smiType;
for (smiNode = smiGetFirstChildNode(groupNode);
smiNode;
smiNode = smiGetNextChildNode(smiNode)) {
if (smiNode->nodekind & (SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR)
&& (smiNode->access >= SMI_ACCESS_READ_ONLY)) {
if (smiNode->access == SMI_ACCESS_READ_WRITE) {
smiType = smiGetNodeType(smiNode);
if (smiType && smiType->name
&& strcmp(smiType->name, "RowStatus") == 0) {
if (cflag) printCreateMethod(f, groupNode, smiNode);
if (dflag) printDeleteMethod(f, groupNode, smiNode);
} else {
if (! isIndex(groupNode, smiNode)) {
if (sflag) printSetMethod(f, groupNode, smiNode);
}
}
}
}
}
}
static void
printStubMethods(FILE *f, SmiModule *smiModule)
{
SmiNode *smiNode;
int cnt = 0;
const unsigned int groupkind = SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN;
for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
smiNode;
smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
if (isGroup(smiNode, groupkind) && isAccessible(smiNode)) {
cnt++;
printNewMethod(f, smiModule, smiNode);
printAssignMethod(f, smiModule, smiNode);
if (smiNode->nodekind == SMI_NODEKIND_ROW) {
printGetTableMethod(f, smiModule, smiNode);
printGetRowMethod(f, smiModule, smiNode);
if (isWritable(smiNode, SMI_NODEKIND_COLUMN)) {
printSetRowMethod(f, smiModule, smiNode);
}
} else {
printGetScalarsMethod(f, smiModule, smiNode);
if (isWritable(smiNode, SMI_NODEKIND_SCALAR)) {
printSetScalarsMethod(f, smiModule, smiNode);
}
}
printFreeMethod(f, smiModule, smiNode);
if (smiNode->nodekind == SMI_NODEKIND_ROW) {
printFreeTableMethod(f, smiModule, smiNode);
}
printStubMethod2(f, smiNode);
}
}
if (cnt) {
fprintf(f, "\n");
}
}
static void
dumpStubs(SmiModule *smiModule, char *baseName)
{
FILE *f;
f = createFile(baseName, ".c");
if (! f) {
return;
}
fprintTopComment(f, smiModule);
fprintf(f,
"#include \"%s.h\"\n"
"\n",
baseName);
printStubEnumerations(f, smiModule);
printStubIdentities(f, smiModule);
printStubNotifications(f, smiModule);
printStubContraints(f, smiModule);
printStubAttributes(f, smiModule);
printStubMethods(f, smiModule);
if (fflush(f) || ferror(f)) {
perror("smidump: write error");
exit(1);
}
fclose(f);
}
static void
dumpScli(int modc, SmiModule **modv, int flags, char *output)
{
char *baseName;
int i, code;
if (include) {
incl_regex = &_incl_regex;
code = regcomp(incl_regex, include, REG_EXTENDED|REG_NOSUB);
if (code != 0) {
char buffer[256];
regerror(code, incl_regex, buffer, sizeof(buffer));
fprintf(stderr, "smidump: regular expression error: %s\n", buffer);
exit(1);
}
}
if (exclude) {
excl_regex = &_excl_regex;
code = regcomp(excl_regex, exclude, REG_EXTENDED|REG_NOSUB);
if (code != 0) {
char buffer[256];
regerror(code, excl_regex, buffer, sizeof(buffer));
fprintf(stderr, "smidump: regular expression error: %s\n", buffer);
if (incl_regex) {
regfree(incl_regex);
}
exit(1);
}
}
if (flags & SMIDUMP_FLAG_UNITE) {
/* not implemented yet */
} else {
for (i = 0; i < modc; i++) {
baseName = output ? output : translateFileName(modv[i]->name);
dumpHeader(modv[i], baseName);
dumpStubs(modv[i], baseName);
if (! output) xfree(baseName);
}
}
if (incl_regex) {
regfree(incl_regex);
incl_regex = NULL;
}
if (excl_regex) {
regfree(excl_regex);
excl_regex = NULL;
}
}
void initScli()
{
static SmidumpDriverOption opt[] = {
{ "prefix", OPT_STRING, &prefix, 0,
"use prefix instead of module name in stubs"},
{ "include", OPT_STRING, &include, 0,
"include stubs for groups matching a regex"},
{ "exclude", OPT_STRING, &exclude, 0,
"exclude stubs for groups matching a regex"},
{ "set", OPT_FLAG, &sflag, 0,
"generate set stubs for writable objects"},
{ "create", OPT_FLAG, &cflag, 0,
"generate create stubs for tables using RowStatus"},
{ "delete", OPT_FLAG, &dflag, 0,
"generate delete stubs for tables using RowStatus"},
{ 0, OPT_END, 0, 0 }
};
static SmidumpDriver driver = {
"scli",
dumpScli,
0,
SMIDUMP_DRIVER_CANT_UNITE,
"ANSI C manager stubs for the gsnmp package",
opt,
NULL
};
smidumpRegisterDriver(&driver);
}