1#!/bin/sh 2# 3# Copyright (c) 1994-2008 Carnegie Mellon University. All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions 7# are met: 8# 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in 14# the documentation and/or other materials provided with the 15# distribution. 16# 17# 3. The name "Carnegie Mellon University" must not be used to 18# endorse or promote products derived from this software without 19# prior written permission. For permission or any legal 20# details, please contact 21# Carnegie Mellon University 22# Center for Technology Transfer and Enterprise Creation 23# 4615 Forbes Avenue 24# Suite 302 25# Pittsburgh, PA 15213 26# (412) 268-7393, fax: (412) 268-7395 27# innovation@andrew.cmu.edu 28# 29# 4. Redistributions of any form whatsoever must retain the following 30# acknowledgment: 31# "This product includes software developed by Computing Services 32# at Carnegie Mellon University (http://www.cmu.edu/computing/)." 33# 34# CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 35# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 36# AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 37# FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 38# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 39# AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 40# OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 41 42exec perl -x -S $0 ${1+"$@"} # -*-perl-*- 43#!perl -w 44 45if ($] !~ /^5\..*/) { 46 # uh-oh. this isn't perl 5. 47 foreach (split(/:/, $ENV{PATH})) { # try to find "perl5". 48 exec("$_/perl5", "-w", "-x", "-S", $0, @ARGV) if (-x "$_/perl5"); 49 } 50 # we failed. bail. 51 die "Your perl is too old; I need perl 5.\n"; 52} 53 54# load the real script. this is isolated in an 'eval' so perl4 won't 55# choke on the perl5-isms. 56eval join("\n", <DATA>); 57if ($@) { die "$@"; } 58 59__END__ 60require 5; 61 62#Tim Martin 63# 2/10/2000 64 65use Getopt::Long; 66my $opt_extra = undef; 67 68$ret = GetOptions("extra:s"); 69if (!$ret || $#ARGV != 0) { 70 print STDERR "snmpgen [--extra=trailer.in] app.snmp\n"; 71 exit; 72} 73 74$infile = $ARGV[0]; 75 76if ($infile =~ m|.*/(.*)\.snmp|) { 77 $basename = $1; 78} elsif ($infile =~ m|(.*)\.snmp|) { 79 $basename = $1; 80} else { 81 $basename = $infile; 82} 83print "basename $basename\n"; 84$outheader = "$basename.h"; 85$outprog = "$basename.c"; 86 87open (INPUT,"<$infile"); 88 89my $linenum = 0; 90my $found = 0; 91my $base = "NOT"; 92my $num_cmds = 0; 93 94my %T; # maps names to types 95my %D; # maps names to descs 96my %O; # maps names to oids 97 98push @Varlist, "LISTEND"; 99 100#first find the BASE 101while (defined ($line = <INPUT>)) { 102 $linenum++; 103 104 if ($line =~ /^#/) { 105 # comment 106 next; 107 } 108 if ($line =~ /^\s*$/) { 109 # just whitespace. ignore 110 next; 111 } 112 113 if ($line =~ /^define\s+(\w+)\s+((\d|\.|\[\w+\])+)/) 114 { 115 $defname = $1; 116 $defoid = $2; 117 118 #resolve definitions 119 while ($defoid =~ /(\[(\w+)\])/) 120 { 121 my $f = 0; 122 foreach my $a (keys %Definelist) 123 { 124 if ($a eq $2) 125 { 126 $defoid =~ s/\[\w+\]/$Definelist{$a}/; 127 $f = 1; 128 } 129 } 130 if ($f == 0) { 131 die "Unable to resolve definition $2"; 132 } 133 } 134 135 $Definelist{$defname} = $defoid; 136 next; 137 } 138 139 if ($line =~ /^var\s+(\w+)/) { 140 push @Varlist, $1; 141 next; 142 } 143 144 if ($line =~ /^BASE\s+((\d+|\.|\{\w+\}|\[\w+\])+)/) { 145 $base = $1; 146 147 #resolve definitions 148 while ($base =~ /(\[(\w+)\])/) 149 { 150 my $f = 0; 151 foreach my $a (keys %Definelist) 152 { 153 if ($a eq $2) 154 { 155 $base =~ s/\[\w+\]/$Definelist{$a}/; 156 $f = 1; 157 } 158 } 159 if ($f == 0) { 160 die "Unable to resolve definition $2"; 161 } 162 } 163 164 #add lowest base to register list 165 if ($base =~ /((\d+\.)+\d+)/) { 166 push @Registerlist, $1; 167 } 168 169 undef @baseVlist; 170 #xxx check all vars in varlist 171 while ($base =~ /(\{(\w+)\})/) 172 { 173 push @baseVlist, $2; 174 $base =~ s/\{\w+\}/%d/; 175 } 176 177 $basecount = 0; 178 next; 179 } 180 181 chomp $line; 182 ($type, $name, $desc, $oid, $dummy) = split(/\s*,\s*/, $line, 5); 183 184 if (!(defined $oid) || (defined $dummy)) { 185 die "syntax error on line $linenum\n"; 186 } 187 188 if ($oid eq "auto") { 189 $oid = $base . ".$basecount"; 190 $basecount++; 191 } else { 192 $oid = $base . "." . $oid; 193 } 194 195 $T{$name} = $type; 196 $D{$name} = $desc; 197 $O{$name} = $oid; 198 $Ovlist{$name} = [ @baseVlist ]; 199} 200 201open (OUTPUT_H, ">$outheader"); 202 203print OUTPUT_H <<EOF 204/* $outheader -- statistics push interface 205 * generated automatically from $infile by snmpgen 206 * 207 * Copyright 2000 Carnegie Mellon University 208 * 209 * No warranty, yadda yadda 210 */ 211 212#ifndef ${basename}_H 213#define ${basename}_H 214 215EOF 216; 217 218foreach my $a (keys %Definelist) 219{ 220 print OUTPUT_H "#define SNMPDEFINE_$a \"$Definelist{$a}\"\n"; 221} 222 223print OUTPUT_H <<EOF 224 225#ifndef USING_SNMPGEN 226 227#define snmp_connect() 228#define snmp_close() 229#define snmp_increment(a, b) 230#define snmp_increment_args(a, b, c, d, e) 231#define snmp_set(a, b) 232#define snmp_set_str(a, b) 233#define snmp_set_oid(a, b) 234#define snmp_set_time(a, b) 235#define snmp_getdescription(a) 236#define snmp_getoid(a, b, c, d) 237#define snmp_setvariable(a, b) 238 239typedef void ${basename}_t; 240 241#else 242 243typedef enum { 244EOF 245; 246 247# Avoid putting a comma after the last item as not every C compiler 248# accepts it 249my $initialized = 0; 250foreach my $name (keys %T) { 251 print OUTPUT_H ",\n" if $initialized; 252 print OUTPUT_H " $name"; 253 $initialized = 1; 254} 255 256print OUTPUT_H <<EOF 257} ${basename}_t; 258 259typedef enum { 260EOF 261; 262 263$initialized = 0; 264foreach my $name (@Varlist) { 265 print OUTPUT_H ",\n" if $initialized; 266 print OUTPUT_H " VARIABLE_$name"; 267 $initialized = 1; 268} 269 270 271print OUTPUT_H <<EOF 272 273} ${basename}_variable_t; 274 275int snmp_connect(void); 276 277int snmp_close(void); 278 279/* only valid on counters */ 280int snmp_increment(${basename}_t cmd, int); 281int snmp_increment_args(${basename}_t cmd, int incr, ...); 282 283/* only valid on values */ 284int snmp_set(${basename}_t cmd, int); 285 286int snmp_set_str(${basename}_t cmd, char *value); 287 288int snmp_set_oid(${basename}_t cmd, char *str); 289 290int snmp_set_time(${basename}_t cmd, time_t t); 291 292const char *snmp_getdescription(${basename}_t cmd); 293 294const char *snmp_getoid(const char *name, ${basename}_t cmd, char* buf, int buflen); 295 296void snmp_setvariable(${basename}_variable_t, int); 297 298#endif /* USING_SNMPGEN */ 299 300#endif /* ${basename}_H */ 301 302EOF 303; 304 305close OUTPUT_H; 306 307open (OUTPUT_C,">$outprog"); 308 309print OUTPUT_C <<EOF 310/* $outprog -- automatically generated from $infile by snmpgen */ 311 312#ifdef USING_SNMPGEN 313 314/* We disable this code for now since it doesn't actually work and wastes 315 * resources. At some point in time, we'll make it work again as it would 316 * be useful to gather aggregate statistics on what commands are being used 317 * so we can better tune the server. This change closes bug #1191. 318 * New bug 1267 opened to re-enable the feature. 319 */ 320 321#ifdef HAVE_UNISTD_H 322#include <unistd.h> 323#endif 324#include <stdio.h> 325#include <stdlib.h> 326#include <errno.h> 327#include <string.h> 328#include <sys/types.h> 329#include <sys/socket.h> 330#include <sys/un.h> 331#include <fcntl.h> 332#include <stdarg.h> 333 334#include "index.h" 335#include "$outheader" 336 337extern int close(int); 338 339int variable_value[$#Varlist+1]; 340int variable_tmpvalue[$#Varlist+1]; 341 342int varvalue(${basename}_variable_t var) 343{ 344 if (variable_tmpvalue[var]!=-1) 345 return variable_tmpvalue[var]; 346 347 return variable_value[var]; 348} 349 350const char *snmp_getdescription(${basename}_t evt) 351{ 352 switch (evt) { 353EOF 354; 355 356foreach my $a (keys %T) 357{ 358 print OUTPUT_C " case $a: return $D{$a};\n"; 359} 360 361print OUTPUT_C <<EOF 362 } 363 return NULL; 364} 365 366const char *snmp_getoid(const char *name __attribute__((unused)), 367 ${basename}_t evt, char *buf, int buflen) 368{ 369 switch (evt) { 370EOF 371; 372 373foreach my $a (keys %T) 374{ 375 print OUTPUT_C " case $a: snprintf(buf,buflen,\"$O{$a}\""; 376 foreach my $b (@{ $Ovlist{$a} }) 377 { 378 print OUTPUT_C ",varvalue(VARIABLE_$b)"; 379 } 380 print OUTPUT_C "); return buf;\n"; 381 382} 383 384 385$snmp.= " default: return \"0.0.0\";\n"; 386$snmp.= " }\n"; 387$snmp.= "}\n"; 388 389print OUTPUT_C <<EOF 390 } 391 return NULL; 392} 393 394#define SOCK_PATH "/tmp/.snmp_door" 395 396static int mysock = -1; 397static struct sockaddr_un remote; 398static int sockaddr_len = 0; 399 400static void snmp_send(char *str) 401{ 402 if (mysock == -1) return; 403 404 if (sendto(mysock, str, strlen(str), 0, (struct sockaddr *) &remote, sockaddr_len) == -1) { 405 return; 406 } 407 408 return; 409} 410 411int snmp_connect(void) 412{ 413 int s; 414 int fdflags; 415 int lup; 416 417 if ((s = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) { 418 return 1; 419 } 420 421 for (lup=0;lup < $#Varlist+1; lup++) 422 variable_tmpvalue[lup] = -1; 423 424 remote.sun_family = AF_UNIX; 425 strlcpy(remote.sun_path, SOCK_PATH, sizeof(remote.sun_path)); 426 sockaddr_len = strlen(remote.sun_path) + sizeof(remote.sun_family); 427 428 /* put us in non-blocking mode */ 429 fdflags = fcntl(s, F_GETFD, 0); 430 if (fdflags != -1) fdflags = fcntl(s, F_SETFL, O_NONBLOCK | fdflags); 431 if (fdflags == -1) { close(s); return -1; } 432 433 mysock = s; 434EOF 435; 436 437foreach my $oid (@Registerlist) { 438 print OUTPUT_C " snmp_send(\"R $oid\\n\");\n"; 439} 440 441 442print OUTPUT_C <<EOF 443 return 0; 444} 445 446int snmp_close(void) 447{ 448 if (mysock > -1) 449 close(mysock); 450 451 return 0; 452} 453 454int snmp_increment_args(${basename}_t cmd, int incr, ...) 455{ 456 char tosend[256]; /* xxx UDP max size??? */ 457 char buf[256]; 458 459 va_list ap; /* varargs thing */ 460 ${basename}_variable_t vval; 461 int ival; 462 463 if (mysock == -1) return 1; 464 465 va_start(ap, incr); 466 467 do { 468 vval = va_arg(ap, ${basename}_variable_t); /* get the next arg */ 469 470 if (vval!=VARIABLE_LISTEND) 471 { 472 ival = va_arg(ap, int); /* get the next arg */ 473 variable_tmpvalue[vval] = ival; 474 } 475 476 } while ( vval != VARIABLE_LISTEND); 477 478 va_end(ap); 479 480 snprintf(tosend, sizeof(tosend),"C %s %d\\n",snmp_getoid(NULL,cmd,buf,sizeof(buf)), incr); 481 482 if (sendto(mysock, tosend, strlen(tosend), 0, (struct sockaddr *) &remote, sockaddr_len) == -1) { 483 return 1; 484 } 485 486 /* set tmp variables back */ 487 va_start(ap, incr); 488 489 do { 490 vval = va_arg(ap, ${basename}_variable_t); /* get the next arg */ 491 492 if (vval!=VARIABLE_LISTEND) 493 { 494 ival = va_arg(ap, int); /* get the next arg */ 495 variable_tmpvalue[vval] = -1; 496 } 497 498 } while ( vval != VARIABLE_LISTEND); 499 500 va_end(ap); 501 502 return 0; 503} 504 505int snmp_increment(${basename}_t cmd, int incr) 506{ 507 char tosend[256]; /* xxx UDP max size??? */ 508 char buf[256]; 509 510 if (mysock == -1) return 1; 511 512 snprintf(tosend, sizeof(tosend),"C %s %d\\n",snmp_getoid(NULL,cmd,buf,sizeof(buf)), incr); 513 514 if (sendto(mysock, tosend, strlen(tosend), 0, (struct sockaddr *) &remote, sockaddr_len) == -1) { 515 return 1; 516 } 517 518 return 0; 519} 520 521int snmp_set(${basename}_t cmd, int value) 522{ 523 char tosend[256]; 524 char buf[256]; 525 526 if (mysock == -1) return 1; 527 528 snprintf(tosend, sizeof(tosend),"I %s %d\\n",snmp_getoid(NULL,cmd,buf,sizeof(buf)), value); 529 530 if (sendto(mysock, tosend, strlen(tosend), 0, (struct sockaddr *) &remote, sockaddr_len) == -1) { 531 return 1; 532 } 533 534 return 1; 535} 536 537int snmp_set_str(${basename}_t cmd, char *value) 538{ 539 char tosend[256]; 540 char buf[256]; 541 542 if (mysock == -1) return 1; 543 544 snprintf(tosend, sizeof(tosend),"S %s %s\\n",snmp_getoid(NULL,cmd,buf,sizeof(buf)), value); 545 546 if (sendto(mysock, tosend, strlen(tosend), 0, (struct sockaddr *) &remote, sockaddr_len) == -1) { 547 return 1; 548 } 549 550 return 1; 551} 552 553int snmp_set_time(${basename}_t cmd, time_t t) 554{ 555 char tosend[256]; 556 char buf[256]; 557 558 if (mysock == -1) return 1; 559 560 snprintf(tosend, sizeof(tosend),"T %s %lu\\n",snmp_getoid(NULL,cmd,buf,sizeof(buf)), t); 561 562 if (sendto(mysock, tosend, strlen(tosend), 0, (struct sockaddr *) &remote, sockaddr_len) == -1) { 563 return 1; 564 } 565 566 return 1; 567} 568 569/* should use SNMPDEFINE's as parameter */ 570int snmp_set_oid(${basename}_t cmd, char *str) 571{ 572 return snmp_set_str(cmd,str); 573} 574 575void snmp_setvariable(${basename}_variable_t name, int value) 576{ 577 variable_value[name] = value; 578} 579 580#endif 581 582 583EOF 584; 585 586if (defined $opt_extra) { 587 open (INPUT_IN,"<$opt_extra"); 588 while( <INPUT_IN> ) 589 { 590 print OUTPUT_C; 591 } 592 close INPUT_IN; 593} 594 595close OUTPUT_C; 596 597