/* * 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 #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_WIN_H #include "win.h" #endif #include "smi.h" #include "smidump.h" #include #ifdef HAVE_REGEX_H #include #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); }