- (mib2c): created a mib2c template creator.


git-svn-id: file:///home/hardaker/lib/sf-bkups/net-snmp-convert-svnrepo/trunk@1357 06827809-a52a-0410-b366-d66718629ded
diff --git a/local/mib2c b/local/mib2c
new file mode 100755
index 0000000..f10e698
--- /dev/null
+++ b/local/mib2c
@@ -0,0 +1,279 @@
+#!/usr/local/bin/perl -w
+
+#
+# Description: 
+#
+# This program, given an OID reference as an argument, creates some
+# template mib module files to be used with the ucd-snmp agent.  It is
+# far from perfect and will not generate working modules, but it
+# significantly shortens development time by outlining the basic
+# structure.
+#
+# Its up to you to verify what it does and change the default values
+# it returns.
+#
+# You *must* correct the beginning of the var_XXX() function to
+# correctly determine mib ownership of the incoming request.
+#
+
+use SNMP;
+#use strict 'vars';
+$SNMP::save_descriptions=1;
+$SNMP::use_long_names=1;
+$SNMP::use_enums=1;
+SNMP::initMib();
+
+#
+# internal conversion tables
+#
+%typeToVar = qw(OctetStr string Objid objid Integer long_ret NetAddr objid 
+		Ipaddr objid Counter long_ret Gauge long_ret Timeticks long_ret
+		UInteger long_ret);
+
+%typeToPtr = qw(OctetStr string Objid objid Integer &long_ret NetAddr objid 
+		Ipaddr objid Counter &long_ret Gauge &long_ret 
+		Timeticks &long_ret UInteger &long_ret);
+
+%typeToParser = qw(OctetStr string Objid objid Integer int NetAddr objid 
+		Ipaddr objid Counter int Gauge int Timeticks int
+		UInteger unsigned_int);
+
+%varDefaults = ('long_ret' => 
+"      long_ret = 0;
+      return (unsigned char *) &long_ret;\n", 
+		'objid' =>
+"      objid[0] = 0;
+      objid[1] = 0;
+      *var_len = 2*sizeof(oid);
+      return (unsigned char *) objid;\n",
+
+		'string' => 
+"      *string = 0;
+      *var_len = strlen(string);
+      return (unsigned char *) string;\n");
+
+%typeToASN = qw(OctetStr ASN_OCTET_STR Objid ASN_OBJECT_ID Integer ASN_INTEGER
+		NetAddr ASN_OBJECT_ID Ipaddr ASN_IPADDRESS Counter ASN_COUNTER
+		Gauge ASN_GAUGE Timeticks ASN_TIMETICKS
+		UInteger ASN_UINTEGER);
+
+%accessToUCD = qw(ReadOnly RONLY ReadWrite RWRITE 
+		  WriteOnly RWRITE Create RWRITE);
+
+@varLengths = (2,4,7,8,13);
+
+$oid = shift;
+
+if (!defined($oid)) {
+    print STDERR "You didn\'t specify a mib oid to convert!\n";
+    exit(1);
+}
+
+$mib = $SNMP::MIB{$oid};
+$_ = $fulloid = $mib->{'objectID'};
+if (!defined ($fulloid)) {
+    print STDERR "Couldn\'t find mib reference: $oid\n";
+    exit(1);
+}
+
+s/[^.]//g;
+$fulllen = length($_);
+$outputName = shift;
+$outputName = $mib->{'label'} if (!defined($outputName));
+$OUTPUTNAME = uc($outputName);
+print "outputing to $outputName.c and $outputName.h ...\n";
+
+open(DOTH,">$outputName.h");
+open(DOTC,">$outputName.c");
+print DOTH "
+/* This file was generated by mib2c and is intended for use as a mib module
+   for the ucd-snmp snmpd agent. */
+
+#ifndef _MIBGROUP_${OUTPUTNAME}_H
+#define _MIBGROUP_${OUTPUTNAME}_H
+
+/* we use header_generic and checkmib from the util_funcs module */
+
+config_require(util_funcs)
+
+/* Magic number definitions: */\n\n";
+
+print DOTC "
+/* This file was generated by mib2c and is intended for use as a mib module
+   for the ucd-snmp snmpd agent. */
+
+#include <config.h>
+
+#include \"mibincl.h\"
+#include \"$outputName.h\"
+
+void init_$outputName __P((void)) {
+/* place any initialization routines needed here */
+}
+
+unsigned char *
+var_$outputName(vp, name, length, exact, var_len, write_method)
+    struct variable *vp;
+    oid     *name;
+    int     *length;
+    int     exact;
+    int     *var_len;
+    int     (**write_method) __P((int, unsigned char *,unsigned char, int, unsigned char *,oid*, int));
+{
+
+  /* variables we may use later */
+  static long long_ret;
+  static unsigned char string[1500];
+  static oid objid[30];
+
+  *write_method = 0;           /* assume it isnt writable for the time being */
+  *var_len = sizeof(long_ret); /* assume an integer and change later if not */
+
+  /* XXX: this following line is almost gaurunteed to be wrong for
+  your mib, please fix this */
+  if (!checkmib(vp,name,length,exact,var_len,write_method,newname,1)))
+      return 0;
+
+  /* this is where we do the value assignments for the mib results. */
+  switch(vp->magic) {\n\n";
+
+#
+# Collect mib information
+#
+$count = 0;
+$depth = loadMib($mib,0,0)-1;
+for($varlen = 0; $varlen <= $#varLengths; $varlen++) {
+  last if ($depth <= $varLengths[$varlen]);
+}
+$varlen = $varLengths[$varlen];
+
+print DOTC "    default:
+      ERROR_MSG(\"\");
+  }
+  return 0;
+}
+
+$writeInfo";
+
+print DOTH "
+/* function definitions */
+
+extern void   init_$outputName __P((void));
+extern unsigned char *var_$outputName __P((struct variable *, oid *, int *, int, int *, int (**write) __P((int, unsigned char *, unsigned char, int, unsigned char *, oid *, int)) ));
+$functionInfo
+
+/* Only load this structure when this .h file is called in the snmp_vars.c 
+   file in tha agent subdirectory of the source tree */
+
+#ifdef IN_SNMP_VARS_C
+
+/* this variable defines function callbacks and type return information 
+   for the $outputName mib */
+
+struct variable$varlen ${outputName}_variables[] = {
+$structinfo
+};
+
+/* now load this mib into the agents mib table */
+config_load_mib(" . substr($fulloid,1) . ", $fulllen, ${outputName}_variables)
+
+#endif /* IN_SNMP_VARS_C */
+#endif /* _MIBGROUP_${OUTPUTNAME}_H */\n";
+
+#
+# Writable variable code
+#
+close(DOTH);
+close(DOTC);
+print "  depth: $depth\n";
+print "  Number of Lines Created:\n";
+system("wc -l $outputName.c $outputName.h");
+print "Done.\n";
+
+sub loadMib {
+    my $mib = shift;
+#    my $oid = shift;
+    my $depth = shift;
+    $depth = $depth + 1;
+#    my $mib = $SNMP::MIB{$oid};
+#    print "doing $mib->{label} : $mib->{objectID}\n";
+    if (defined($mib->{'access'}) && 
+	$mib->{'access'} =~ /ReadOnly|ReadWrite|WriteOnly|Create/) {
+	my $cname = uc($mib->{'label'});
+	print DOTC "    case $cname:\n";
+	if (!defined($typeToVar{$mib->{'type'}})) {
+	    print DOTC "/* unknown type: $mib->{type}.  mib2c can not set up a default value for this mib value */.";
+	    print STDERR "unknown type:  $mib->{type} for $mib->{label}\n";
+	} else {
+	    if ($mib->{'access'} =~ /ReadWrite|WriteOnly|Create/) {
+		createWriteFunction($mib->{'label'}, $mib->{'type'});
+		print DOTC "      *write_method = write_$mib->{label};\n";
+	    }
+	    print DOTC $varDefaults{$typeToVar{$mib->{'type'}}}, "\n";
+	    $count = $count + 1;
+	    printf DOTH ("#define   %-20s  $count\n", $cname);
+	    $subid = $mib->{'objectID'};
+	    $subid =~ s/$fulloid\.//;
+	    $subid =~ s/\./,/g;
+	    $structinfo .= 
+		sprintf("  { %-20s, %-14s, %-6.6s, %s, %d, { %s } },\n",
+			$cname, $typeToASN{$mib->{'type'}},
+			$accessToUCD{$mib->{'access'}},
+			"var_$outputName",
+			$depth-1, $subid);
+	}
+    }
+    my $children = $$mib{'children'}; 
+    my $i;
+    my $newdepth = $depth;
+    foreach $i (@{$children}) {
+	$newdepth = max(loadMib($i, $depth), $newdepth);
+    }
+    return $newdepth;
+}
+
+sub max {
+    my $x = shift;
+    my $y = shift;
+    return ($x > $y) ? $x : $y;
+}
+
+sub createWriteFunction {
+    my $name = shift;
+    my $type = shift;
+
+    $writeInfo .= "int
+write_$name(action, var_val, var_val_type, var_val_len, statP, name, name_len)
+   int      action;
+   u_char   *var_val;
+   u_char   var_val_type;
+   int      var_val_len;
+   u_char   *statP;
+   oid      *name;
+   int      name_len;
+{
+  /* variables we may use later */
+  static long long_ret;
+  static unsigned char string[1500];
+  static oid objid[30];
+  int size, bigsize=1000;
+
+  if (var_val_type != $typeToASN{$type}){
+      fprintf(stderr, \"write to $name not $typeToASN{$type}\\n\");
+      return SNMP_ERR_WRONGTYPE;
+  }
+  if (var_val_len > sizeof($typeToVar{$type})){
+      printf(\"bad length\\n\");
+      return SNMP_ERR_WRONGLENGTH;
+  }
+  size = sizeof($typeToVar{$type});
+  asn_parse_$typeToParser{$type}(var_val, &bigsize, &var_val_type, $typeToPtr{$type}, size);
+  if (action == COMMIT){
+      /* Here, the variable has been stored in $typeToVar{$type} for
+      you to use, and you have just been asked to do something with
+      it... Your code goes here. */
+  }
+  return SNMP_ERR_NOERROR;
+}\n\n";
+    $functionInfo .= "int write_$name __P((int, u_char *,u_char, int, u_char *,oid*, int));\n";
+}