1 |
27 |
unneback |
#!/usr/bin/perl
|
2 |
|
|
#!/usr/bin/perl -w
|
3 |
|
|
|
4 |
|
|
#
|
5 |
|
|
# Description:
|
6 |
|
|
#
|
7 |
|
|
# This program, given an OID reference as an argument, creates some
|
8 |
|
|
# template mib module files to be used with the ucd-snmp agent. It is
|
9 |
|
|
# far from perfect and will not generate working modules, but it
|
10 |
|
|
# significantly shortens development time by outlining the basic
|
11 |
|
|
# structure.
|
12 |
|
|
#
|
13 |
|
|
# Its up to you to verify what it does and change the default values
|
14 |
|
|
# it returns.
|
15 |
|
|
#
|
16 |
|
|
|
17 |
|
|
use SNMP;
|
18 |
|
|
use FileHandle;
|
19 |
|
|
|
20 |
|
|
#use strict 'vars';
|
21 |
|
|
$SNMP::save_descriptions=1;
|
22 |
|
|
$SNMP::use_long_names=1;
|
23 |
|
|
$SNMP::use_enums=1;
|
24 |
|
|
SNMP::initMib();
|
25 |
|
|
|
26 |
|
|
$configfile="mib2c.conf";
|
27 |
|
|
$debug=0;
|
28 |
|
|
$nostats = 0;
|
29 |
|
|
|
30 |
|
|
sub usage {
|
31 |
|
|
print "$0 [-h] [-c configfile] [-f prefix] mibNode\n\n";
|
32 |
|
|
print " -h\t\tThis message.\n\n";
|
33 |
|
|
print " -c configfile\tSpecifies the configuration file to use\n\t\tthat dictates what the output of mib2c will look like.\n\n";
|
34 |
|
|
print " -f prefix\tSpecifies the output prefix to use. All code\n\t\twill be put into prefix.c and prefix.h\n\n";
|
35 |
|
|
print " mibNode\tThe name of the top level mib node you want to\n\t\tgenerate code for. By default, the code will be stored in\n\t\tmibNode.c and mibNode.h (use the -f flag to change this)\n\n";
|
36 |
|
|
print " -d\t\tdebugging output (dont do it. trust me.)\n\n";
|
37 |
|
|
print " -s\t\tDon't display statistics at the end\n\n";
|
38 |
|
|
1;
|
39 |
|
|
}
|
40 |
|
|
|
41 |
|
|
while($#ARGV >= 0) {
|
42 |
|
|
$_ = shift;
|
43 |
|
|
$configfile = shift if (/-c/);
|
44 |
|
|
$debug = 1 if (/-d/);
|
45 |
|
|
$nostats = 1 if (/-s/);
|
46 |
|
|
usage && exit(1) if (/-h/);
|
47 |
|
|
$outputName = shift if (/-f/);
|
48 |
|
|
$oid = $_ if (/^[^-]/);
|
49 |
|
|
}
|
50 |
|
|
|
51 |
|
|
read_config($configfile);
|
52 |
|
|
#
|
53 |
|
|
# internal conversion tables
|
54 |
|
|
#
|
55 |
|
|
|
56 |
|
|
%accessToUCD = qw(ReadOnly RONLY ReadWrite RWRITE
|
57 |
|
|
WriteOnly RWRITE Create RWRITE);
|
58 |
|
|
|
59 |
|
|
# The lengths of the defined 'variableN' structures
|
60 |
|
|
@varLengths = (2,4,7,8,13);
|
61 |
|
|
|
62 |
|
|
if (!defined($oid)) {
|
63 |
|
|
print STDERR "You didn\'t specify a mib oid to convert!\n";
|
64 |
|
|
usage();
|
65 |
|
|
exit(1);
|
66 |
|
|
}
|
67 |
|
|
|
68 |
|
|
$mib = $SNMP::MIB{$oid};
|
69 |
|
|
$_ = $commaoid = $fulloid = $mib->{'objectID'};
|
70 |
|
|
if (!defined ($fulloid)) {
|
71 |
|
|
print STDERR "Couldn\'t find mib reference: $oid\n";
|
72 |
|
|
exit(1);
|
73 |
|
|
}
|
74 |
|
|
s/[^.]//g;
|
75 |
|
|
$commaoid =~ s/\./,/g;
|
76 |
|
|
$commaoid =~ s/^,//g;
|
77 |
|
|
|
78 |
|
|
$outputName = $mib->{'label'} if (!defined($outputName));
|
79 |
|
|
$OUTPUTNAME = uc($outputName);
|
80 |
|
|
$vroutine="$outputName";
|
81 |
|
|
print "outputting to $outputName.c and $outputName.h ...\n";
|
82 |
|
|
|
83 |
|
|
#============================================
|
84 |
|
|
#
|
85 |
|
|
# Walk the MIB tree, and construct strings
|
86 |
|
|
# holding the various fragments of code needed.
|
87 |
|
|
#
|
88 |
|
|
# 'loadMib' returns the length of the longest OID suffix
|
89 |
|
|
# encountered.
|
90 |
|
|
#
|
91 |
|
|
# The variables constructed and used are:
|
92 |
|
|
#
|
93 |
|
|
# (in the header file)
|
94 |
|
|
# functionInfo : A list of definitions for the table-handling functions,
|
95 |
|
|
# and routines for SETtable variables.
|
96 |
|
|
# (The main scalar handling routine is handled implicitly)
|
97 |
|
|
#
|
98 |
|
|
# (in the code file)
|
99 |
|
|
# structinfo : The contents of the variableN structure listing
|
100 |
|
|
# the variables handled, including type, access level,
|
101 |
|
|
# OID suffix and 'magic number'
|
102 |
|
|
#
|
103 |
|
|
# caseStatements: A hash array (indexed by variable routine name)
|
104 |
|
|
# containing the body of the switch statement
|
105 |
|
|
# used for returning the appropriate values.
|
106 |
|
|
# At a minimum, this consists of the various 'case' labels
|
107 |
|
|
# If full type information is available (from mib2c.conf)
|
108 |
|
|
# then this will also include a default initialiser,
|
109 |
|
|
# and setting of a 'write_method' (if appropriate).
|
110 |
|
|
#
|
111 |
|
|
# writeFuncs: A list of function skeletons for setting variables
|
112 |
|
|
# (for variables with suitable access levels).
|
113 |
|
|
# Note that this list will not include functions
|
114 |
|
|
# for variables which don't provide type information
|
115 |
|
|
# in the mib2c.conf file (even if such variables are
|
116 |
|
|
# defined as writeable in the variableN structure).
|
117 |
|
|
#
|
118 |
|
|
#============================================
|
119 |
|
|
$count = 0;
|
120 |
|
|
$depth = loadMib($mib,0)-1;
|
121 |
|
|
|
122 |
|
|
# Determine which 'variableN' structure is needed
|
123 |
|
|
for($varlen = 0; $varlen <= $#varLengths; $varlen++) {
|
124 |
|
|
last if ($depth <= $varLengths[$varlen]);
|
125 |
|
|
}
|
126 |
|
|
$varlen = $varLengths[$varlen];
|
127 |
|
|
|
128 |
|
|
#============================================
|
129 |
|
|
#
|
130 |
|
|
# Table-handling routines.
|
131 |
|
|
#
|
132 |
|
|
#============================================
|
133 |
|
|
foreach $vtable (@table_list) {
|
134 |
|
|
foreach $ptable (@processtable) {
|
135 |
|
|
$variables{$ptable}{'processed'} .=
|
136 |
|
|
(eval "\"$variables{$ptable}{'code'}\"") . "\n\n";
|
137 |
|
|
}
|
138 |
|
|
$var_routines .=
|
139 |
|
|
(eval "\"$variables{'code-var_table'}{'code'}\"") . "\n\n";
|
140 |
|
|
}
|
141 |
|
|
|
142 |
|
|
#============================================
|
143 |
|
|
#
|
144 |
|
|
# Output the header file
|
145 |
|
|
#
|
146 |
|
|
#============================================
|
147 |
|
|
open(DOTH,">$outputName.h");
|
148 |
|
|
print DOTH (eval "\"$variables{'code-dot-h'}{'code'}\"") . "\n";
|
149 |
|
|
close(DOTH);
|
150 |
|
|
|
151 |
|
|
#============================================
|
152 |
|
|
#
|
153 |
|
|
# Output the code file:
|
154 |
|
|
# Initialisation and main variable routine.
|
155 |
|
|
#
|
156 |
|
|
#============================================
|
157 |
|
|
|
158 |
|
|
open(DOTC,">$outputName.c");
|
159 |
|
|
print DOTC (eval "\"$variables{'code-main-part'}{'code'}\"") . "\n\n";;
|
160 |
|
|
close(DOTC);
|
161 |
|
|
|
162 |
|
|
#============================================
|
163 |
|
|
#
|
164 |
|
|
# Everyone loves statistics.
|
165 |
|
|
#
|
166 |
|
|
#============================================
|
167 |
|
|
print " depth: $depth\n";
|
168 |
|
|
print " Number of Lines Created:\n";
|
169 |
|
|
system("wc -l $outputName.c $outputName.h");
|
170 |
|
|
print "Done.\n";
|
171 |
|
|
|
172 |
|
|
#============================================
|
173 |
|
|
#
|
174 |
|
|
# loadMib:
|
175 |
|
|
# Recursive routine to walk the mib,
|
176 |
|
|
# and construct the various code fragment strings.
|
177 |
|
|
#
|
178 |
|
|
#============================================
|
179 |
|
|
sub loadMib {
|
180 |
|
|
my $mib = shift;
|
181 |
|
|
my $i;
|
182 |
|
|
my $depth = shift;
|
183 |
|
|
$depth = $depth + 1;
|
184 |
|
|
my $name = $mib->{'label'};
|
185 |
|
|
my $NAME = uc($name);
|
186 |
|
|
print "doing $mib->{label} : $mib->{objectID}\n" if $debug;
|
187 |
|
|
if (defined($mib->{'access'}) &&
|
188 |
|
|
$mib->{'access'} =~ /ReadOnly|ReadWrite|WriteOnly|Create|NoAccess/) {
|
189 |
|
|
$count = $count + 1;
|
190 |
|
|
$subid = $mib->{'objectID'};
|
191 |
|
|
$subid =~ s/$fulloid\.//;
|
192 |
|
|
$subid =~ s/\./,/g;
|
193 |
|
|
if (!defined($variables{$mib->{'type'}}) && !defined($mib->{'indexes'})) {
|
194 |
|
|
print STDERR "unknown type: $mib->{type} for $mib->{label} $mib->{'access'}\n";
|
195 |
|
|
print STDERR "unknown type: no information generated for $mib->{label}\n";
|
196 |
|
|
} else {
|
197 |
|
|
foreach $i (@process) {
|
198 |
|
|
next if (defined($variables{$i}{'skipif'}) &&
|
199 |
|
|
eval $variables{$i}{'skipif'});
|
200 |
|
|
my $result = (eval "\"$variables{$i}{'code'}\"");
|
201 |
|
|
$variables{$i}{'processed'} .= "$result\n";
|
202 |
|
|
$variables{$vroutine}{$i}{'processed'} .= "$result\n";
|
203 |
|
|
}
|
204 |
|
|
}
|
205 |
|
|
if (defined($mib->{'indexes'})) {
|
206 |
|
|
print "indexes: ", join(", ",@{$mib->{'indexes'}}),"\n" if ($debug);
|
207 |
|
|
$variables{$vroutine}{'indexes'} = $mib->{'indexes'};
|
208 |
|
|
foreach $i (@{$mib->{'indexes'}}) {
|
209 |
|
|
$variables{$vroutine}{$i}{'isanindex'} = 1;
|
210 |
|
|
}
|
211 |
|
|
}
|
212 |
|
|
}
|
213 |
|
|
my $children = $$mib{'children'};
|
214 |
|
|
my $i;
|
215 |
|
|
my $newdepth = $depth;
|
216 |
|
|
foreach $i (@{$children}) {
|
217 |
|
|
if ( $name =~ /Table$/ ) {
|
218 |
|
|
$vroutine="$name";
|
219 |
|
|
push @table_list, $name;
|
220 |
|
|
$newdepth = max(loadMib($i, $depth), $newdepth);
|
221 |
|
|
$vroutine="$outputName";
|
222 |
|
|
}
|
223 |
|
|
else {
|
224 |
|
|
$newdepth = max(loadMib($i, $depth), $newdepth);
|
225 |
|
|
}
|
226 |
|
|
}
|
227 |
|
|
return $newdepth;
|
228 |
|
|
}
|
229 |
|
|
|
230 |
|
|
sub max {
|
231 |
|
|
my $x = shift;
|
232 |
|
|
my $y = shift;
|
233 |
|
|
return ($x > $y) ? $x : $y;
|
234 |
|
|
}
|
235 |
|
|
|
236 |
|
|
|
237 |
|
|
sub read_config() {
|
238 |
|
|
my $configfile = shift;
|
239 |
|
|
my ($type, $lasttoken);
|
240 |
|
|
my $fh = new FileHandle;
|
241 |
|
|
if ( $fh->open("<$configfile") ) {
|
242 |
|
|
while(<$fh>) {
|
243 |
|
|
next if (/^\s*\#/ || /^\s*$/);
|
244 |
|
|
if (/^\s*type:\s*(.*)/) {
|
245 |
|
|
if (defined($type) && defined($lasttoken) &&
|
246 |
|
|
defined ($variables{$type}{$lasttoken})) {
|
247 |
|
|
chomp($variables{$type}{$lasttoken});
|
248 |
|
|
}
|
249 |
|
|
$type = $1;
|
250 |
|
|
chomp($type);
|
251 |
|
|
} elsif (/include:\s*(.*)/) {
|
252 |
|
|
read_config($1);
|
253 |
|
|
} elsif (/process:\s*(.*)/) {
|
254 |
|
|
push (@process, $1);
|
255 |
|
|
} elsif (/processtable:\s*(.*)/) {
|
256 |
|
|
push (@processtable, $1);
|
257 |
|
|
} elsif (/delete:\s*(.*)/) {
|
258 |
|
|
delete($variables{$type}{$1});
|
259 |
|
|
} elsif (/copy:\s*(.*)/) {
|
260 |
|
|
my $item;
|
261 |
|
|
chomp($1);
|
262 |
|
|
foreach $item (keys(%{$variables{$1}})) {
|
263 |
|
|
$variables{$type}{$item} = $variables{$1}{$item};
|
264 |
|
|
}
|
265 |
|
|
} else {
|
266 |
|
|
if (/\s*([^:]*):(\s*.*)/) {
|
267 |
|
|
if (!defined($variables{$type}{$1})) {
|
268 |
|
|
if (defined($type) && defined($lasttoken) &&
|
269 |
|
|
defined ($variables{$type}{$lasttoken})) {
|
270 |
|
|
chomp($variables{$type}{$lasttoken});
|
271 |
|
|
}
|
272 |
|
|
$variables{$type}{$1} = $2;
|
273 |
|
|
$lasttoken = $1;
|
274 |
|
|
$variables{$type}{$1} =~ s/^\t+//;
|
275 |
|
|
} else {
|
276 |
|
|
# duplicate entry: tack it on.
|
277 |
|
|
my ($x, $y) = ($1, $2);
|
278 |
|
|
$y =~ s/^\t+//;
|
279 |
|
|
$variables{$type}{$x} .= "\n" . $y;
|
280 |
|
|
}
|
281 |
|
|
} else {
|
282 |
|
|
# continuation line, it started with spaces or a +
|
283 |
|
|
s/^\s*//;
|
284 |
|
|
s/^\+//;
|
285 |
|
|
$variables{$type}{$lasttoken} .= "\n" . $_;
|
286 |
|
|
chomp($variables{$type}{$lasttoken});
|
287 |
|
|
}
|
288 |
|
|
}
|
289 |
|
|
}
|
290 |
|
|
$fh->close();
|
291 |
|
|
} else {
|
292 |
|
|
warn "Config file ($configfile) not found.\n";
|
293 |
|
|
}
|
294 |
|
|
}
|
295 |
|
|
|
296 |
|
|
sub evalstr {
|
297 |
|
|
my $str = shift;
|
298 |
|
|
# if ($str !~ /^\"/) {
|
299 |
|
|
$str = "\"$str\""; # surround by quotes.
|
300 |
|
|
# }
|
301 |
|
|
eval ($str); # should return a string, with variables expanded
|
302 |
|
|
}
|
303 |
|
|
|
304 |
|
|
sub evalrstr {
|
305 |
|
|
my $rstr = shift;
|
306 |
|
|
# if ($str !~ /^\"/) {
|
307 |
|
|
# $$rstr = "\"" . $$rstr . "\""; # surround by quotes.
|
308 |
|
|
# }
|
309 |
|
|
eval ("\"$$rstr\""); # should return a string, with variables expanded
|
310 |
|
|
}
|