Index: vendor/bsnmp/1.13/Makefile.in =================================================================== --- vendor/bsnmp/1.13/Makefile.in (nonexistent) +++ vendor/bsnmp/1.13/Makefile.in (revision 336778) @@ -0,0 +1,50 @@ +# Copyright (c) 2001-2003 +# Fraunhofer Institute for Open Communication Systems (FhG Fokus). +# All rights reserved. +# +# Author: Harti Brandt +# +# $Begemot: bsnmp/tags/RELENG_1_13/Makefile.in 2238 2018-06-27 14:58:50Z brandt_h $ +# + +SUBDIR= gensnmptree lib snmpd + +ifeq "$(BUILD_MODULES)" "yes" +SUBDIR+= snmp_mibII snmp_ntp snmp_target snmp_usm snmp_vacm +endif + +ifeq "$(HAVE_LIBSMI)" "yes" +SUBDIR += gensnmpdef +endif + +PKGFILES=libbsnmp.pc +PKGFILESDIR= ${prefix}/libdata/pkgconfig + +all: + +@for f in $(SUBDIR) ; do \ + echo "==> $$f" ; \ + if ! $(MAKE) -C $$f all ; then \ + break ; \ + fi ; \ + done + +install: + +@for f in $(SUBDIR) ; do \ + echo "==> $$f" ; \ + if ! $(SUBMAKE) -C $$f install ; then \ + break ; \ + fi ; \ + done + @$(srcdir)/config/mkinstalldirs $(PKGFILESDIR) + for f in $(PKGFILES) ; do \ + $(BSD_INSTALL_DATA) $(builddir)/$$f $(PKGFILESDIR) ; \ + done + +clean: + +@for f in $(SUBDIR) ; do \ + echo "==> $$f" ; \ + if ! $(SUBMAKE) -C $$f clean ; then \ + break ; \ + fi ; \ + done + -rm -f $(PKGFILES) Property changes on: vendor/bsnmp/1.13/Makefile.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/NEWS =================================================================== --- vendor/bsnmp/1.13/NEWS (nonexistent) +++ vendor/bsnmp/1.13/NEWS (revision 336778) @@ -0,0 +1,194 @@ +1.12a + Support for ENUM and BITS in gensnmp{tree,def}. Include directives + and typedefs. + +1.12 + A couple of man page fixes from various submitters. + + Make default communities NULL for security. + + Fix a core dump when -d tracing suboption has no argument (thanks + to Shteryana Shopova). + + Fix bug in parsing the include path in the daemon. + + Fix an uninitialize structure field in gensnmptree (thanks to + jasone@freebsdorg) + + 64bit HC counters in the IF-MIB by polling the OS periodically. + + Fix link traps to be more RFC conform (thanks to glebius@freebsd.org) + + Add fallback definition for SA_SIZE() to support.h. + + Move the porting definitions for U?INT32_{MIN,MAX} into support.h. + + Include a sys/tree.h from FreeBSD-current and add autoconf + check for it. + +1.11a Fix build of modules when stdint.h is included after asn1.h + +1.11 Make the Mib2 routing table use red-black tree. This vastly + reduces loading and access time. Load the table only every 10 + minutes. In the meantime process message from the routing socket + to update the table. + + Lot of man-page fixes from ru@freebsd.org. + + Fixes to command line macros and macro redefinition. + + Trap variables for ntp (still need trap definition and code). + + Periodic timers from Victor Cruceru. + + Man-page fixes from Christian Brueffer. + + Lots of spelling fixes from Giorgios Keramidas. + + A number of changes to facilitate building on FreeBSD-4 from + Andrey Elsukov. + + Add repeatable timers. + +1.10 + Change all the tick handling in the daemon from 32-bit to 64-bit. + Bump the modules' major version number to 3. + + snmp_dialog: make the syntax of the variable bindings in the outgoing + message SNMP_SYNTAX_NULL regardless of the syntax given by the user. + + Fix an error in timer handling in the LIBBEGEMOT case. + + snmpd/main.c: Fix a 64-bit warning. + + lib/snmpclient: Add snmp_parse_server(). + +1.9 + tcpwrapper support from glebius@freebsd.org. + + crude interface to NTP: snmp_ntp + +1.8 + many man page fixes from ru@freebsd.org and tobez@freebsd.org + + snmpd/main.c: fix a problem which resulted in the daemon exiting + when a local socket was closed. + + snmpd/trans_lsock.c: include stdio.h to get a prototype for remove. + + gensnmptree/gensnmptree.c: fix a compile error + + snmp_mibII: add new field spec_oid to ifmib. This allows ifType + specific modules to insert the value to be returned for ifSpecific. + +1.7a + fix core dump when config file cannot be opened (submitted by + Maxim Konovalov) + +1.7 + snmpd: Move event library initialization before reading of + config file (thanks to phk). + + gensnmptree: can now read more than one tree and merge them. + + some support for compilation on older systems + + use standard C fixed width integer types [u]intNN_t + +1.6 + New gensnmpdef tool. Needs libsmi. + + Make build infrastructure more intelligent. + + Fix a typo in the mibII counter retrival code. + + Add a new field to struct snmp_node for snmp agents: tree_data. + This field can be used by the application. + + Fix a syntax error in the example configuration file (thanks to + David J Duchscher). + + Fix a long standing problem with the module loading code + and a memory leak. When a module could not be loaded usually + a core dump was generated. This was caused by wrong handling + of malloced memory in the module table dependency. While + fixing this problem it became obvious that dynamic allocated + data which was held in a dependency could be lost, because + there was no guarantee that the dependency handler ever was + call (in case of an error in a SET handler or an earlier + dependency in the same PDU) thus causing this memory to leak. + To fix this a third dependency operation is introduced + SNMP_DEPOP_FINISH which is invoked just before a dependency + is freed at the very end of the SET PDU handling. This + means also that finalizers (set_atfinish) can be converted + to DEPOP_FINISH handler in almost all cases. The only case + where this is not so easy is when a finializer was registered + for a simple SET operation. In this case an artifical dependency + would be needed. Because this seems to occure very seldom the + snmp_set_atfinish() call is removed. Thanks to Paul-Henning Kamp + for an initial fix for the core dump. + +09-Dec-2003 + First step on factoring out the transport mapping stuff into + loadable modules. + + Local stream sockets that check the clients privileges. + +03-Dec-2003 + Bump version to 1.5 but leave library version intact. + +03-Dec-2003 + Now works with libbegemot polling stuff instead of libisc. + Use --with-libbegemot[=path] to configure. + +03-Dec-2003 + Fix parsing of non-minimal ASN.1 integers. They are now disallowed. + Non-minimal lengths are allowed. + + Remove copyright clause 3 everywhere. + + Make an autoconf build infrastructure. + +08-Nov-2003 + WARNS=6 fixed. + +28-Jan-2003 + WARNS=5 fixes. + +09-Jan-2003 + snmpd: remove local socket in case of an error to fully initialize it. + Use chmod instead of fchmod. The latter seems not really to change + the mode of the socket. + + lib: at program exit remove the local socket in the library. + +11-Dec-2002 + Implement listening on unix domain sockets. The client must bind + its socket, or the server cannot send back its response. These + sockets are considered to be more secure, because it is much + harder for an intruder to listen on them. + + This requires changes in snmpmod.h and snmpclient.h. + +04-Dec-2002 + Sparc fixes. + +15-Aug-2002 + Use inttypes.h instead of limits.h to get integer limits. This + seems to be the Posix way. + + First drafts of an snmpd, gensnmptree, asn1, bsnmplib, + bsnmpclient, bsnmpagent, snmpmod, snmp_mibII, snmp_netgraph man pages. + + snmpd/main.c: reorder getopt options according to style(9). Implement + a -h option to print a short help. + +25-Jun-2002 + Makefiles rewritten to not use bsnmpmod.mk. The BSD makefiles are + really hard to use, because a) they are not documented and b) they + change much too often. + + Make the patch a context diff instead of a unified one. + +28-Feb-2002 + Library code for SNMP clients. Property changes on: vendor/bsnmp/1.13/NEWS ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/README =================================================================== --- vendor/bsnmp/1.13/README (nonexistent) +++ vendor/bsnmp/1.13/README (revision 336778) @@ -0,0 +1,65 @@ +Fri Dec 5 15:01:16 CET 2003 + +This is a mini-SNMP daemon. The basic daemon implements the system group +and a number of private extensions to manage the UDP transport mapping, +communities, trap destinations and loadable modules. In this form it can +be used to provide remote access to arbitrary data that can be described in +the form as required by the SMI. The daemon speaks both SNMPv1 and SNMPv2c. + +One basic loadable module is provided together with the daemon: + +- snmp_mibII provides the information groups for ip, tcp, and udp. + +Installation +------------ + +As usual by doing: + + configure [--with-libbegemot[=path]] + make + make install + +This does not install a configuration file. The standard location for the +configuration is /etc/snmpd.config, but can be overwritten on the command +line. An example configuration file is provided. Use --with-libbegemot +to use libbegemot instead of libisc. + +Running +------- + + snmpd [-m name[=value]] [-p pid-file] [-c config-file] [-d] [-l prefix] + [-D debug-flags] [-I path] + + -m defines a configuration macro. If no value is given it + is set to the empty string. + + -p specify the file where to store the PID. Default is + /var/run/{prefix}.pid. + + -c specify the configuration file. Default is /etc/{prefix}.config. + + -d don't go into daemon mode. + + -l specify the prefix. This is used for the default config and + pid file names and for the syslog. Default is "snmpd". + + -D specify debug flags: + + d dump all PDUs. + + e debug event library. + + -I specify the include path for system configuration files. + Default is /etc:/usr/etc:/usr/local/etc. + +The directory snmpd contains a snmpd.sh script, which can be copied to +/usr/local/etc/rc.d to automatically start and stop the daemon. snmpd.config +is an example config script. + +Bug reports: +----------- + +Please report bugs to harti@freebsd.org. + +Happy hacking, +harti Property changes on: vendor/bsnmp/1.13/README ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/README.1st =================================================================== --- vendor/bsnmp/1.13/README.1st (nonexistent) +++ vendor/bsnmp/1.13/README.1st (revision 336778) @@ -0,0 +1,5 @@ +Make the infrastructure: + + libtoolize -c + aclocal + autoconf Property changes on: vendor/bsnmp/1.13/README.1st ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/TODO =================================================================== --- vendor/bsnmp/1.13/TODO (nonexistent) +++ vendor/bsnmp/1.13/TODO (revision 336778) @@ -0,0 +1,14 @@ +snmpd: + - rethink transports a little bit: make them loadable and make + a private subtree for transports: + OK. Table not writeable yet. + + There should be a transport table that is indexed by the transport name. + This table can be used to load/unload transports at run time. + OK. Table not writeable yet. + + Then there can be a port table that is indexed by transport name and + port name. Plus a transport-specific table indexed by port name only. + + The transport table could contain a column of type OID that points + to the transport-specific table. Property changes on: vendor/bsnmp/1.13/TODO ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/VERSION =================================================================== --- vendor/bsnmp/1.13/VERSION (nonexistent) +++ vendor/bsnmp/1.13/VERSION (revision 336778) @@ -0,0 +1 @@ +1.13 Property changes on: vendor/bsnmp/1.13/VERSION ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/config/Makefile.build =================================================================== --- vendor/bsnmp/1.13/config/Makefile.build (nonexistent) +++ vendor/bsnmp/1.13/config/Makefile.build (revision 336778) @@ -0,0 +1,11 @@ +# Copyright (c) 2004 +# Hartmut Brandt +# All rights reserved. +# +# Author: Harti Brandt +# +# $Begemot: bsnmp/trunk/config/Makefile.build 1487 2008-12-23 19:03:33Z brandt_h $ +# + +all: build-prog build-lib build-man1 build-man3 + Property changes on: vendor/bsnmp/1.13/config/Makefile.build ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/config/Makefile.post =================================================================== --- vendor/bsnmp/1.13/config/Makefile.post (nonexistent) +++ vendor/bsnmp/1.13/config/Makefile.post (revision 336778) @@ -0,0 +1,129 @@ +# Copyright (c) 2001-2003 +# Fraunhofer Institute for Open Communication Systems (FhG Fokus). +# All rights reserved. +# +# Author: Harti Brandt +# +# $Begemot: bsnmp/trunk/config/Makefile.post 2117 2015-09-16 14:09:31Z brandt_h $ +# + +.SUFFIXES: .lo +.c.lo: + @test -d .deps || mkdir .deps >/dev/null 2>&1 + $(LIBTOOL) --tag=CC --mode=compile $(CC) -c $(CFLAGS) -o $@ $< + +$(LIBTOOL): $(LIBTOOL_DEPS) + $(SHELL) ../config.status --recheck + +clean: + rm -rf *.o .libs .deps *.a *.la *.lo $(PROG) $(LIB) core $(PROG).core $(CLEANFILES) + +DEPENDS=$(patsubst %.c,.deps/%.d, $(patsubst %.h,, $(SRCS))) + +ifndef MANFILTER +MANFILTER=cat +endif + +ifneq "$(MAN1)" "" +build-man1: $(MAN1:%.1=%.1out) + +install-man1: + @$(srcdir)/../config/mkinstalldirs $(mandir)/man1 + for f in $(MAN1) ; do \ + $(BSD_INSTALL_MAN) $${f}out $(mandir)/man1/$${f} ; \ + done + +%.1out: %.1 + cat $< | $(MANFILTER) >$@ + +else +build-man1: +install-man1: +endif + +ifneq "$(MAN3)" "" +build-man3: $(MAN3:%.3=%.3out) + +install-man3: + @$(srcdir)/../config/mkinstalldirs $(mandir)/man3 + for f in $(MAN3) ; do \ + $(BSD_INSTALL_MAN) $${f}out $(mandir)/man3/$${f} ; \ + done + +%.3out: %.3 + cat $< | $(MANFILTER) >$@ +else +build-man3: +install-man3: +endif + +ifneq "$(DEFS)" "" +install-defs: + @$(srcdir)/../config/mkinstalldirs $(DEFSDIR) + $(BSD_INSTALL_DATA) $(DEFS:%=$(srcdir)/%) $(DEFSDIR) + +DEFSDIR= ${datadir}/snmp/defs + +else +install-defs: +endif + +ifneq "$(INCS)" "" + +INCDIR= $(includedir)/bsnmp + +install-incs: + @$(srcdir)/../config/mkinstalldirs $(INCDIR) + for f in $(INCS) ; do \ + if [ -r $(builddir)/$$f ] ; then \ + $(BSD_INSTALL_DATA) $(builddir)/$$f $(INCDIR) ; \ + else \ + $(BSD_INSTALL_DATA) $(srcdir)/$$f $(INCDIR) ; \ + fi ; \ + done + +else +install-incs: +endif + +ifneq "$(BMIBS)" "" + +BMIBSDIR= ${datadir}/snmp/mibs + +install-mibs: + @$(srcdir)/../config/mkinstalldirs $(BMIBSDIR) + for f in $(BMIBS) ; do \ + $(BSD_INSTALL_DATA) $(srcdir)/$$f $(BMIBSDIR) ; \ + done + +else +install-mibs: +endif + +ifneq "$(PROG)" "" +build-prog: $(PROG) + +install-prog: + @$(srcdir)/../config/mkinstalldirs $(bindir) + $(LIBTOOL) --mode=install $(BSD_INSTALL_PROGRAM) $(builddir)/$(PROG) $(bindir)/$(PROG) + +else +build-prog: +install-prog: +endif + +ifneq "$(LIB)" "" +build-lib: $(LIB) + +install-lib: + @$(srcdir)/../config/mkinstalldirs $(libdir) + $(LIBTOOL) --mode=install $(BSD_INSTALL_DATA) $(LIB) $(libdir) + +else +build-lib: +install-lib: +endif + +install: install-prog install-lib install-incs install-man1 install-man3 install-defs install-mibs + +-include /dev/null $(DEPENDS) Property changes on: vendor/bsnmp/1.13/config/Makefile.post ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/config/Makefile.pre =================================================================== --- vendor/bsnmp/1.13/config/Makefile.pre (nonexistent) +++ vendor/bsnmp/1.13/config/Makefile.pre (revision 336778) @@ -0,0 +1,68 @@ +# Copyright (c) 2004-2005 +# Hartmut Brandt. +# All rights reserved. +# Copyright (c) 2001-2003 +# Fraunhofer Institute for Open Communication Systems (FhG Fokus). +# All rights reserved. +# +# Author: Harti Brandt +# +# $Begemot: bsnmp/trunk/config/Makefile.pre 2117 2015-09-16 14:09:31Z brandt_h $ +# + +@SET_MAKE@ + +VPATH+= @srcdir@ + +srcdir= @srcdir@ +top_builddir= @top_builddir@ +builddir= @builddir@ +prefix= @prefix@ +exec_prefix= @exec_prefix@ +bindir= @bindir@ +sbindir= @sbindir@ +libdir= @libdir@ +includedir= @includedir@ +mandir= @mandir@ +datadir= @datadir@ +datarootdir= @datarootdir@ + +INSTALL= @INSTALL@ +INSTALL_PROGRAM= @INSTALL_PROGRAM@ +INSTALL_DATA= @INSTALL_DATA@ +INSTALL_SCRIPT= @INSTALL_SCRIPT@ + +ifndef BSD_INSTALL_MAN +BSD_INSTALL_MAN = ${INSTALL_DATA} +endif +ifndef BSD_INSTALL_DATA +BSD_INSTALL_DATA = ${INSTALL_DATA} +endif +ifndef BSD_INSTALL_PROGRAM +BSD_INSTALL_PROGRAM = ${INSTALL_PROGRAM} +endif + +LIBTOOL= @LIBTOOL@ +LIBTOOL_DEPS= @LIBTOOL_DEPS@ +SHELL = @SHELL@ +CC= @CC@ +DEFINES=@DEFS@ +CPPFLAGS= @CPPFLAGS@ +CFLAGS= @CFLAGS@ +LDFLAGS= @LDFLAGS@ + +LIBEV= @LIBEV@ +LIBWRAP= @LIBWRAP@ +LIBDL= @LIBDL@ + +# Assume a Posix-ish make that passes MAKEFLAGS in the environment. +SUBMAKE= $(MAKE) --no-print-directory + +WARNS= @WARNS@ + +CFLAGS+= $(WARNS) -Wp,-MD,.deps/$(*F).d +CFLAGS+= $(DEFINES) + +HAVE_LIBSMI=@HAVE_LIBSMI@ + +BUILD_MODULES=@BUILD_MODULES@ Property changes on: vendor/bsnmp/1.13/config/Makefile.pre ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/config/config.guess =================================================================== --- vendor/bsnmp/1.13/config/config.guess (nonexistent) +++ vendor/bsnmp/1.13/config/config.guess (revision 336778) @@ -0,0 +1,1433 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2015 Free Software Foundation, Inc. + +timestamp='2015-03-04' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# +# Please send patches to . + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2015 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + /sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || \ + echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` + machine=${arch}${endian}-unknown + ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # Determine ABI tags. + case "${UNAME_MACHINE_ARCH}" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}${abi}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + *:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + e2k:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: Property changes on: vendor/bsnmp/1.13/config/config.guess ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/bsnmp/1.13/config/config.sub =================================================================== --- vendor/bsnmp/1.13/config/config.sub (nonexistent) +++ vendor/bsnmp/1.13/config/config.sub (revision 336778) @@ -0,0 +1,1804 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2015 Free Software Foundation, Inc. + +timestamp='2015-03-08' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2015 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | amd64-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | e2k-* | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | powerpcspe-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + asmjs) + basic_machine=asmjs-unknown + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* | -cloudabi* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: Property changes on: vendor/bsnmp/1.13/config/config.sub ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/bsnmp/1.13/config/install-sh =================================================================== --- vendor/bsnmp/1.13/config/install-sh (nonexistent) +++ vendor/bsnmp/1.13/config/install-sh (revision 336778) @@ -0,0 +1,527 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2011-11-20.07; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: Property changes on: vendor/bsnmp/1.13/config/install-sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/bsnmp/1.13/config/ltmain.sh =================================================================== --- vendor/bsnmp/1.13/config/ltmain.sh (nonexistent) +++ vendor/bsnmp/1.13/config/ltmain.sh (revision 336778) @@ -0,0 +1,11147 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 + +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +PROGRAM=libtool +PACKAGE=libtool +VERSION=2.4.6 +package_revision=2.4.6 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-01-20.17; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac +fi + +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" + fi" +done + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac + + +## ----------------- ## +## Standard options. ## +## ----------------- ## + +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. + +opt_dry_run=false +opt_quiet=false +opt_verbose=false + +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= + +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue + +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all + + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1+=\\ \$func_quote_for_eval_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1=\$$1\\ \$func_quote_for_eval_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" + fi +} + + +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () +{ + $debug_cmd + + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} + + +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () +{ + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_for_eval ARG... +# -------------------------- +# Aesthetically quote ARGs to be evaled later. +# This function returns two values: +# i) func_quote_for_eval_result +# double-quoted, suitable for a subsequent eval +# ii) func_quote_for_eval_unquoted_result +# has all characters that are still active within double +# quotes backslashified. +func_quote_for_eval () +{ + $debug_cmd + + func_quote_for_eval_unquoted_result= + func_quote_for_eval_result= + while test 0 -lt $#; do + case $1 in + *[\\\`\"\$]*) + _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; + *) + _G_unquoted_arg=$1 ;; + esac + if test -n "$func_quote_for_eval_unquoted_result"; then + func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" + else + func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" + fi + + case $_G_unquoted_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_quoted_arg=\"$_G_unquoted_arg\" + ;; + *) + _G_quoted_arg=$_G_unquoted_arg + ;; + esac + + if test -n "$func_quote_for_eval_result"; then + func_append func_quote_for_eval_result " $_G_quoted_arg" + else + func_append func_quote_for_eval_result "$_G_quoted_arg" + fi + shift + done +} + + +# func_quote_for_expand ARG +# ------------------------- +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + $debug_cmd + + case $1 in + *[\\\`\"]*) + _G_arg=`$ECHO "$1" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; + *) + _G_arg=$1 ;; + esac + + case $_G_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_arg=\"$_G_arg\" + ;; + esac + + func_quote_for_expand_result=$_G_arg +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_for_expand "$_G_cmd" + eval "func_notquiet $func_quote_for_expand_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_for_expand "$_G_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2014-01-07.03; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook funcions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + eval $_G_hook '"$@"' + + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + done + + func_quote_for_eval ${1+"$@"} + func_run_hooks_result=$func_quote_for_eval_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, remove any +# options that you action, and then pass back the remaining unprocessed +# options in '_result', escaped suitably for +# 'eval'. Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# +# func_quote_for_eval ${1+"$@"} +# my_options_prep_result=$func_quote_for_eval_result +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# ;; +# *) set dummy "$_G_opt" "$*"; shift; break ;; +# esac +# done +# +# func_quote_for_eval ${1+"$@"} +# my_silent_option_result=$func_quote_for_eval_result +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# func_quote_for_eval ${1+"$@"} +# my_option_validation_result=$func_quote_for_eval_result +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll alse need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + func_options_prep ${1+"$@"} + eval func_parse_options \ + ${func_options_prep_result+"$func_options_prep_result"} + eval func_validate_options \ + ${func_parse_options_result+"$func_parse_options_result"} + + eval func_run_hooks func_options \ + ${func_validate_options_result+"$func_validate_options_result"} + + # save modified positional parameters for caller + func_options_result=$func_run_hooks_result +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propogate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning. +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + func_run_hooks func_options_prep ${1+"$@"} + + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + func_parse_options_result= + + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + func_run_hooks func_parse_options ${1+"$@"} + + # Adjust func_parse_options positional parameters to match + eval set dummy "$func_run_hooks_result"; shift + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + test $# = 0 && func_missing_arg $_G_opt && break + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + func_parse_options_result=$func_quote_for_eval_result +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + func_run_hooks func_validate_options ${1+"$@"} + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 +} + + +# func_missing_arg ARGNAME +# ------------------------ +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $debug_cmd + + func_error "Missing argument for '$1'." + exit_cmd=exit +} + + +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () +{ + $debug_cmd + + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} + + +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} + + +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () +{ + $debug_cmd + + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () +{ + $debug_cmd + + $warning_func ${1+"$@"} +} + + +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname (GNU libtool) 2.4.6 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." +} + + +# func_config +# ----------- +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + + +# func_features +# ------------- +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test yes = "$build_libtool_libs"; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test yes = "$build_old_libs"; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + + +# func_enable_tag TAGNAME +# ----------------------- +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname=$1 + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + + +# func_check_version_match +# ------------------------ +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false + + nonopt= + preserve_args= + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + esac + + # Pass back the list of options. + func_quote_for_eval ${1+"$@"} + libtool_options_prep_result=$func_quote_for_eval_result +} +func_add_hook func_options_prep libtool_options_prep + + +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + libtool_parse_options_result=$func_quote_for_eval_result +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote_for_eval ${1+"$@"} + libtool_validate_options_result=$func_quote_for_eval_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + + + +## ----------- ## +## Main. ## +## ----------- ## + +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if 'file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case $lalib_p_line in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test yes = "$lalib_p" +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $debug_cmd + + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# 'FILE.' does not work on cygwin managed mounts. +func_source () +{ + $debug_cmd + + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case $lt_sysroot:$1 in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result='='$func_stripname_result + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $debug_cmd + + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with '--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' + else + write_lobj=none + fi + + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $debug_cmd + + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result= + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $debug_cmd + + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $debug_cmd + + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $debug_cmd + + if test -z "$2" && test -n "$1"; then + func_error "Could not determine host file name corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result=$1 + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $debug_cmd + + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " '$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result=$3 + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $debug_cmd + + case $4 in + $1 ) func_to_host_path_result=$3$func_to_host_path_result + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via '$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $debug_cmd + + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $debug_cmd + + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result=$1 +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result=$func_convert_core_msys_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via '$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $debug_cmd + + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd=func_convert_path_$func_stripname_result + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $debug_cmd + + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result=$1 +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + +# func_mode_compile arg... +func_mode_compile () +{ + $debug_cmd + + # Get the compilation command and the source file. + base_compile= + srcfile=$nonopt # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg=$arg + arg_mode=normal + ;; + + target ) + libobj=$arg + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify '-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs=$IFS; IFS=, + for arg in $args; do + IFS=$save_ifs + func_append_quoted lastarg "$arg" + done + IFS=$save_ifs + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg=$srcfile + srcfile=$arg + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with '-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj=$func_basename_result + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from '$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name '$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test yes = "$build_old_libs"; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test yes = "$need_locks"; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test warn = "$need_locks"; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test yes = "$build_libtool_libs"; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test no != "$pic_mode"; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test yes = "$suppress_opt"; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test yes = "$compiler_c_o"; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test no != "$need_locks"; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a 'standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to '-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the '--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the 'install' or 'cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with '-') are ignored. + +Every other argument is treated as a filename. Files ending in '.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. + +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode '$opt_mode'" + ;; + esac + + echo + $ECHO "Try '$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test : = "$opt_help"; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + $SED '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $debug_cmd + + # The first argument is the command name. + cmd=$nonopt + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "'$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "'$file' was not linked with '-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir=$func_dirname_result + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir=$func_dirname_result + ;; + + *) + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir=$absdir + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic=$magic + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file=$progdir/$program + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file=$progdir/$program + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd=\$cmd$args + fi +} + +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $debug_cmd + + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "'$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument '$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and '=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_quiet && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the '$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $debug_cmd + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac + then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=false + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=: ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the '$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir=$func_dirname_result + destname=$func_basename_result + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "'$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "'$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir=$func_dirname_result + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking '$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname=$1 + shift + + srcname=$realname + test -n "$relink_command" && srcname=${realname}T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme=$stripme + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try 'ln -sf' first, because the 'ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib=$destdir/$realname + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name=$func_basename_result + instname=$dir/${name}i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest=$destfile + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to '$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test yes = "$build_old_libs"; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext= + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=.exe + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script '$wrapper'" + + finalize=: + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test no = "$fast_install" && test -n "$relink_command"; then + $opt_dry_run || { + if $finalize; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file=$func_basename_result + outputname=$tmpdir/$file + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_quiet || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink '$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file=$outputname + else + func_warning "cannot relink '$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name=$func_basename_result + + # Set up the ranlib parameters. + oldlib=$destdir/$name + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run '$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test install = "$opt_mode" && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms=${my_outputname}S.c + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist=$output_objdir/$my_outputname.nm + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* External symbol declarations for the compiler. */\ +" + + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols=$output_objdir/$outputname.exp + $opt_dry_run || { + $RM $export_symbols + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from '$dlprefile'" + func_basename "$dlprefile" + name=$func_basename_result + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename= + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname"; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename=$func_basename_result + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename"; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + $my_pic_p && pic_flag_for_symtable=" $pic_flag" + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + + # Transform the symbol file into the correct name. + symfileobj=$output_objdir/${my_outputname}S.$objext + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for '$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $debug_cmd + + win32_libid_type=unknown + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s|.*|import| + p + q + } + }'` + ;; + esac + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $debug_cmd + + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $debug_cmd + + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1"; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result= + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test yes = "$lock_old_archive_extraction"; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $debug_cmd + + my_gentop=$1; shift + my_oldlibs=${1+"$@"} + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib=$func_basename_result + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" + cd "$darwin_curdir" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result=$my_oldobjs +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory where it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test yes = "$fast_install"; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + \$ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* declarations of non-ANSI functions */ +#if defined __MINGW32__ +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined __CYGWIN__ +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined other_platform || defined ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined _MSC_VER +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +#elif defined __MINGW32__ +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined __CYGWIN__ +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined other platforms ... */ +#endif + +#if defined PATH_MAX +# define LT_PATHMAX PATH_MAX +#elif defined MAXPATHLEN +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free (stale); stale = 0; } \ +} while (0) + +#if defined LT_DEBUGWRAPPER +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + size_t tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined HAVE_DOS_BASED_FILE_SYSTEM + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined HAVE_DOS_BASED_FILE_SYSTEM + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = (size_t) (q - p); + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (STREQ (str, pat)) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + size_t len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + size_t orig_value_len = strlen (orig_value); + size_t add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[--len] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $debug_cmd + + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $debug_cmd + + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # what system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll that has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + os2dllname= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=false + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module=$wl-single_module + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg=$1 + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir=$arg + prev= + continue + ;; + dlfiles|dlprefiles) + $preload || { + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=: + } + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test no = "$dlself"; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test dlprefiles = "$prev"; then + dlself=yes + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test dlfiles = "$prev"; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols=$arg + test -f "$arg" \ + || func_fatal_error "symbol file '$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex=$arg + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + if test none != "$pic_object"; then + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + fi + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file '$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; + precious_regex) + precious_files_regex=$arg + prev= + continue + ;; + release) + release=-$arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test rpath = "$prev"; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds=$arg + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg=$arg + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "'-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test X-export-symbols = "X$arg"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between '-L' and '$1'" + else + func_fatal_error "need path for '-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test X-lc = "X$arg" || test X-lm = "X$arg"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test X-lc = "X$arg" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test X-lc = "X$arg" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test X-lc = "X$arg" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test X-lc = "X$arg" && continue + ;; + esac + elif test X-lc_r = "X$arg"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -mllvm) + prev=mllvm + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module=$wl-multi_module + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -os2dllname) + prev=os2dllname + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -stdlib=* select c++ std lib with clang + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + fi + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + test none = "$pic_object" || { + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + } + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test dlfiles = "$prev"; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test dlprefiles = "$prev"; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the '$prevarg' option requires an argument" + + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname=$func_basename_result + libobjs_save=$libobjs + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + + func_dirname "$output" "/" "" + output_objdir=$func_dirname_result$objdir + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test lib = "$linkmode"; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=false + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test lib,link = "$linkmode,$pass"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs=$tmp_deplibs + fi + + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs + deplibs= + fi + if test prog = "$linkmode"; then + case $pass in + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test lib,dlpreopen = "$linkmode,$pass"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs=$dlprefiles + fi + if test dlopen = "$pass"; then + # Collect dlpreopened libraries + save_deplibs=$deplibs + deplibs= + fi + + for deplib in $libs; do + lib= + found=false + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test lib = "$linkmode"; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib=$searchdir/lib$name$search_ext + if test -f "$lib"; then + if test .la = "$search_ext"; then + found=: + else + found=false + fi + break 2 + fi + done + done + if $found; then + # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll=$l + done + if test "X$ll" = "X$old_library"; then # only static version available + found=false + func_dirname "$lib" "" "." + ladir=$func_dirname_result + lib=$ladir/$old_library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + *.ltframework) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test conv = "$pass" && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + if test scan = "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "'-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test link = "$pass"; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=false + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=: + fi + ;; + pass_all) + valid_a_lib=: + ;; + esac + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + fi + ;; + esac + continue + ;; + prog) + if test link != "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=: + continue + ;; + esac # case $deplib + + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "'$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir=$func_dirname_result + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test conv = "$pass"; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib=$l + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + + # This library was specified with -dlopen. + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test -z "$dlname" || + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir=$ladir + fi + ;; + esac + func_basename "$lib" + laname=$func_basename_result + + # Find the relevant object directory and library name. + if test yes = "$installed"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir + else + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir + fi + test yes = "$hardcode_automatic" && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir=$ladir + absdir=$abs_ladir + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + fi + case $host in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test lib = "$linkmode"; then + deplibs="$dir/$old_library $deplibs" + elif test prog,link = "$linkmode,$pass"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test prog = "$linkmode" && test link != "$pass"; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if $linkalldeplibs; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test prog,link = "$linkmode,$pass"; then + if test -n "$library_names" && + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + # Make sure the rpath contains only unique directories. + case $temp_rpath: in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test built = "$use_static_libs" && test yes = "$installed"; then + use_static_libs=no + fi + if test -n "$library_names" && + { test no = "$use_static_libs" || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc* | *os2*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test no = "$installed"; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule= + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule=$dlpremoduletest + break + fi + done + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + echo + if test prog = "$linkmode"; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname=$1 + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname=$dlname + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc* | *os2*) + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + esac + eval soname=\"$soname_spec\" + else + soname=$realname + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot=$soname + func_basename "$soroot" + soname=$func_basename_result + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from '$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for '$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test prog = "$linkmode" || test relink != "$opt_mode"; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test no = "$hardcode_direct"; then + add=$dir/$linklib + case $host in + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir=-L$dir ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we cannot + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library"; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add=$dir/$old_library + fi + elif test -n "$old_library"; then + add=$dir/$old_library + fi + fi + esac + elif test no = "$hardcode_minus_L"; then + case $host in + *-*-sunos*) add_shlibpath=$dir ;; + esac + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + relink) + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test yes != "$lib_linked"; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test prog = "$linkmode"; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test prog = "$linkmode" || test relink = "$opt_mode"; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add=-l$name + elif test yes = "$hardcode_automatic"; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib + else + add=$libdir/$linklib + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir=-L$libdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + fi + + if test prog = "$linkmode"; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test prog = "$linkmode"; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test yes = "$build_libtool_libs"; then + # Not a shared library + if test pass_all != "$deplibs_check_method"; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system cannot link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test yes = "$module"; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test lib = "$linkmode"; then + if test -n "$dependency_libs" && + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs=$temp_deplibs + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test no != "$link_all_deplibs"; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path=$deplib ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + path= + fi + fi + ;; + *) + path=-L$absdir/$objdir + ;; + esac + else + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "'$deplib' seems to be moved" + + path=-L$absdir + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test link = "$pass"; then + if test prog = "$linkmode"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test dlopen != "$pass"; then + test conv = "$pass" || { + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + } + + if test prog,link = "$linkmode,$pass"; then + vars="compile_deplibs finalize_deplibs" + else + vars=deplibs + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i= + ;; + esac + if test -n "$i"; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test prog = "$linkmode"; then + dlfiles=$newdlfiles + fi + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "'-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "'-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs=$output + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form 'libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" + + if test no != "$need_lib_prefix"; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" + + install_libdir=$1 + + oldlibs= + if test -z "$rpath"; then + if test yes = "$build_libtool_libs"; then + # Building a libtool convenience library. + # Some compilers have problems with a '.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "'-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs=$IFS; IFS=: + set dummy $vinfo 0 0 0 + shift + IFS=$save_ifs + + test -n "$7" && \ + func_fatal_help "too many parameters to '-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major=$1 + number_minor=$2 + number_revision=$3 + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # that has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|freebsd-elf|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_revision + ;; + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_minor + lt_irix_increment=no + ;; + esac + ;; + no) + current=$1 + revision=$2 + age=$3 + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac + ;; + + freebsd-aout) + major=.$current + versuffix=.$current.$revision + ;; + + freebsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + irix | nonstopux) + if test no = "$lt_irix_increment"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring=$verstring_prefix$major.$revision + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test 0 -ne "$loop"; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring_prefix$major.$iface:$verstring + done + + # Before this point, $major must not contain '.'. + major=.$major + versuffix=$major.$revision + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision + + # Add in all the interfaces that we are compatible with. + loop=$age + while test 0 -ne "$loop"; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring:$iface.0 + done + + # Make executables depend on our current version. + func_append verstring ":$current.0" + ;; + + qnx) + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current + ;; + + sunos) + major=.$current + versuffix=.$current.$revision + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 file systems. + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + + *) + func_fatal_configuration "unknown library version type '$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring=0.0 + ;; + esac + if test no = "$need_version"; then + versuffix= + else + versuffix=.0.0 + fi + fi + + # Remove version info from name if versioning should be avoided + if test yes,no = "$avoid_version,$need_version"; then + major= + versuffix= + verstring= + fi + + # Check to see if the archive will have undefined symbols. + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi + fi + else + # Don't allow undefined symbols. + allow_undefined_flag=$no_undefined_flag + fi + + fi + + func_generate_dlsyms "$libname" "$libname" : + func_append libobjs " $symfileobj" + test " " = "$libobjs" && libobjs= + + if test relink != "$opt_mode"; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles=$dlfiles + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles=$dlprefiles + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test yes = "$build_libtool_libs"; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test yes = "$build_libtool_need_lc"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release= + versuffix= + major= + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib=$potent_lib + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib=$potent_lib # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs= + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test none = "$deplibs_check_method"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test yes = "$droppeddeps"; then + if test yes = "$module"; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test no = "$allow_undefined"; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs=$new_libs + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test yes = "$hardcode_into_libs"; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname=$1 + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname=$realname + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib=$output_objdir/$realname + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + func_dll_def_p "$export_symbols" || { + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols=$export_symbols + export_symbols= + always_export_symbols=yes + } + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs=$IFS; IFS='~' + for cmd1 in $cmds; do + IFS=$save_ifs + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test yes = "$try_normal_branch" \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=$output_objdir/$output_la.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs=$tmp_deplibs + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test yes = "$compiler_needs_object" && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test : != "$skipped_export" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test yes = "$compiler_needs_object"; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-$k.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test -z "$objlist" || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test 1 -eq "$k"; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-$k.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-$k.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + } + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs=$IFS; IFS='~' + for cmd in $concat_cmds; do + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + ${skipped_export-false} && { + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + } + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs=$IFS; IFS='~' + for cmd in $cmds; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test yes = "$module" || test yes = "$export_dynamic"; then + # On all known operating systems, these are identical. + dlname=$soname + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "'-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object '$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj=$output + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + else + gentop=$output_objdir/${obj}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + + # Create the old-style object. + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + + output=$obj + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + test yes = "$build_libtool_libs" || { + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + } + + if test -n "$pic_flag" || test default != "$pic_mode"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output=$libobj + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "'-release' is ignored for programs" + + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test CXX = "$tagname"; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs=$new_libs + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath=$rpath + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath=$rpath + + if test -n "$libobjs" && test yes = "$build_old_libs"; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" false + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=: + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=false + ;; + *cygwin* | *mingw* ) + test yes = "$build_libtool_libs" || wrappers_required=false + ;; + *) + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false + fi + ;; + esac + $wrappers_required || { + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command=$compile_command$compile_rpath + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + fi + + exit $exit_status + } + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test yes = "$no_install"; then + # We don't need to create a wrapper script. + link_command=$compile_var$compile_command$compile_rpath + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host"; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience + build_libtool_libs=no + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) + oldobjs="$old_deplibs $non_pic_objects" + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac + + if test -n "$addlibs"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase=$func_basename_result + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj"; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test -z "$oldobjs"; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test yes = "$build_old_libs" && old_library=$libname.$libext + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test yes = "$hardcode_automatic"; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test yes = "$installed"; then + if test -z "$install_libdir"; then + break + fi + output=$output_objdir/${outputname}i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name=$func_basename_result + func_resolve_sysroot "$deplib" + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs=$newdependency_libs + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles=$newdlprefiles + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles=$newdlprefiles + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test -n "$bindir"; then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result/$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test no,yes = "$installed,$need_relink"; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $debug_cmd + + RM=$nonopt + files= + rmforce=false + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=: ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir + else + odir=$dir/$objdir + fi + func_basename "$file" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir + + # Remember odir for removal later, being careful to avoid duplicates + if test clean = "$opt_mode"; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif $rmforce; then + continue + fi + + rmfiles=$file + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case $opt_mode in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && test none != "$pic_object"; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && test none != "$non_pic_object"; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test clean = "$opt_mode"; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the $objdir's in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi + +test -z "$opt_mode" && { + help=$generic_help + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode '$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# where we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: Property changes on: vendor/bsnmp/1.13/config/ltmain.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/config/mkinstalldirs =================================================================== --- vendor/bsnmp/1.13/config/mkinstalldirs (nonexistent) +++ vendor/bsnmp/1.13/config/mkinstalldirs (revision 336778) @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Begemot: bsnmp/trunk/config/mkinstalldirs 1487 2008-12-23 19:03:33Z brandt_h $ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" 1>&2 + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here Property changes on: vendor/bsnmp/1.13/config/mkinstalldirs ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/bsnmp/1.13/configure.ac =================================================================== --- vendor/bsnmp/1.13/configure.ac (nonexistent) +++ vendor/bsnmp/1.13/configure.ac (revision 336778) @@ -0,0 +1,202 @@ +# +# Copyright (c) 2004-2009 +# Hartmut Brandt. +# All rights reserved. +# Copyright (c) 2003-2003 +# Fraunhofer Institute for Open Communication Systems (FhG Fokus). +# All rights reserved. +# +# Author: Harti Brandt +# +# $Begemot: bsnmp/tags/RELENG_1_13/configure.ac 2233 2018-06-25 17:17:57Z brandt_h $ +# +AC_INIT([BSNMP], [1.0], [harti@freebsd.org], bsnmp) +AC_PREREQ(2.53) +AC_COPYRIGHT([Copyright (c)1996-2003 Fraunhofer Fokus. All rights reserved.]) +AC_REVISION($Revision: 382 $) + +AC_CONFIG_MACRO_DIR([m4]) + +AC_CONFIG_SRCDIR(config/install-sh) +AC_CONFIG_AUX_DIR(config) +AC_CANONICAL_BUILD +AC_CANONICAL_HOST +AC_CANONICAL_TARGET + +AC_PROG_CC +AC_PROG_CPP +AC_PROG_MAKE_SET +AC_PROG_INSTALL + +LT_INIT +AC_SUBST(LIBTOOL_DEPS) +AC_SUBST(LIBTOOL) + +#CFLAGS="${CFLAGS} -D_BSD_SOURCE -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_GNU_SOURCE" + +WARNS=" -Wsystem-headers -Werror -Wall -Wno-format-y2k -W \ + -Wstrict-prototypes -Wmissing-prototypes \ + -Wpointer-arith -Wreturn-type -Wcast-qual \ + -Wwrite-strings -Wswitch -Wshadow -Wcast-align \ + -Wbad-function-cast -Wchar-subscripts -Winline \ + -Wnested-externs -Wredundant-decls -std=c99 \ + -Wno-pointer-sign" + +LIBDL= +BUILD_MODULES="yes" + +case $host_os in + linux*) + WARNS+=" -Wno-cast-align -Wno-typedef-redefinition -Wno-builtin-requires-header" + LIBDL="-ldl" + BUILD_MODULES="no" + ;; +esac + +AC_SUBST(WARNS) +AC_SUBST(LIBDL) +AC_SUBST(BUILD_MODULES) + +AC_ARG_WITH(libbegemot, + AC_HELP_STRING([--with-libbegemot], + [use libbegemot instead of libisc and set path to where the +includes and lib are found(default is NO, if no path specified default=/usr/local)]), + ac_cv_use_libbegemot=$withval, ac_cv_use_libbegemot=yes) + +AC_CACHE_CHECK(whether to use libbegemot, + ac_cv_use_libbegemot, ac_cv_use_libbegemot=no) + +if test $ac_cv_use_libbegemot == "yes" ; then + ac_cv_use_libbegemot="/usr/local" +fi + +if test $ac_cv_use_libbegemot != "no" ; then + AC_DEFINE(USE_LIBBEGEMOT) + AC_SUBST(LIBEV, -lbegemot) + + old_CPPFLAGS="$CPPFLAGS" + rpoll_path="" + + CPPFLAGS="$old_CPPLFAGS -I$ac_cv_use_libbegemot/include" + AC_CHECK_HEADERS(rpoll.h, [rpoll_path="$ac_cv_use_libbegemot/include"], + [], [#include + ]) + + if test -z "$rpoll_path" ; then + $as_unset ac_cv_header_rpoll_h + CPPFLAGS="$old_CPPLFAGS -I$ac_cv_use_libbegemot/include/libbegemot" + AC_CHECK_HEADERS(rpoll.h, [rpoll_path="$ac_cv_use_libbegemot/include/libbegemot"]) + fi + + if test -z "$rpoll_path" ; then + AC_MSG_FAILURE([cannot locate rpoll.h]) + fi + + CFLAGS="${CFLAGS} -I$rpoll_path" + LDFLAGS="${LDFLAGS} -L$ac_cv_use_libbegemot/lib" + + AC_CHECK_LIB(begemot, poll_register, , + [AC_ERROR([libbegemot not found])]) + +else + AC_SUBST(LIBEV, -lisc) +fi + +AC_ARG_WITH(tcpwrappers, + AC_HELP_STRING([--with-tcpwrappers], + [use libwrap to control access]), + ac_cv_use_tcpwrappers=$withval, ac_cv_use_tcpwrappers=no) + +if test $ac_cv_use_tcpwrappers != "no" ; then + AC_DEFINE(USE_TCPWRAPPERS) + AC_SUBST(LIBWRAP, -lwrap) +fi + +LDFLAGS="${LDFLAGS} -L/usr/local/lib" + +AC_CHECK_LIB(smi, smiGetNode, HAVE_LIBSMI=yes, HAVE_LIBSMI=no) +AC_SUBST(HAVE_LIBSMI) + +# check for BSD's err.h +AC_CHECK_HEADERS([err.h]) + +# check for strlcpy +AC_CHECK_FUNCS(strlcpy) + +# check for getaddrinfo +AC_CHECK_FUNCS(getaddrinfo) + +# check for a usable tree.h +AC_CHECK_HEADER(sys/tree.h, + AC_DEFINE(HAVE_SYS_TREE_H)) + +# check whether we have posix stdint.h or at least inttypes.h +AC_CHECK_HEADER(stdint.h, + AC_DEFINE(HAVE_STDINT_H)) +AC_CHECK_HEADER(inttypes.h, + [AC_DEFINE(HAVE_INTTYPES_H) + ac_have_inttypes_h=yes]) +AC_CACHE_CHECK([how to print quads], + ac_cv_quad_fmt, + [if test "$ac_have_inttypes_h" = "yes" ; then + AC_EGREP_CPP(yes, +[ +# include +# ifdef PRIu64 +yes +# endif +], + ac_cv_quad_fmt=PRIu64, + AC_TRY_RUN( +[[ +# include +# include +# include +int +main() +{ + char buf[100]; + + sprintf(buf, "%llx", 0x1234567887654321LLU); + exit((strcmp(buf, "1234567887654321") == 0) ? 0 : 1); +} +]], + ac_cv_quad_fmt='"ll"', + ac_cv_quad_fmt='"q"', + ac_cv_quad_fmt='"q"') + fi ])) + +if test "$ac_cv_quad_fmt" = "PRIu64" ; then + AC_DEFINE(QUADFMT, PRIu64) + AC_DEFINE(QUADXFMT, PRIx64) +else + AC_DEFINE_UNQUOTED(QUADFMT, ${ac_cv_quad_fmt}"u") + AC_DEFINE_UNQUOTED(QUADXFMT, ${ac_cv_quad_fmt}"x") +fi + +AC_CHECK_TYPES([u_int, u_char, u_long], [], [], [[#include ]]) + +AC_CHECK_MEMBERS([struct sockaddr_un.sun_len, struct sockaddr_in.sin_len], [], [], [[#include ]]) + +AC_CONFIG_FILES([ + Makefile:config/Makefile.pre:Makefile.in + gensnmpdef/Makefile:config/Makefile.pre:config/Makefile.build:gensnmpdef/Makefile.in:config/Makefile.post + gensnmptree/Makefile:config/Makefile.pre:config/Makefile.build:gensnmptree/Makefile.in:config/Makefile.post + lib/Makefile:config/Makefile.pre:config/Makefile.build:lib/Makefile.in:config/Makefile.post + snmpd/Makefile:config/Makefile.pre:config/Makefile.build:snmpd/Makefile.in:config/Makefile.post + libbsnmp.pc +]) + +case $host_os in + FreeBSD* | freebsd*) + AC_CONFIG_FILES([ + snmp_mibII/Makefile:config/Makefile.pre:config/Makefile.build:snmp_mibII/Makefile.in:config/Makefile.post + snmp_ntp/Makefile:config/Makefile.pre:config/Makefile.build:snmp_ntp/Makefile.in:config/Makefile.post + snmp_target/Makefile:config/Makefile.pre:config/Makefile.build:snmp_target/Makefile.in:config/Makefile.post + snmp_usm/Makefile:config/Makefile.pre:config/Makefile.build:snmp_usm/Makefile.in:config/Makefile.post + snmp_vacm/Makefile:config/Makefile.pre:config/Makefile.build:snmp_vacm/Makefile.in:config/Makefile.post + ]) + ;; +esac + +AC_OUTPUT Property changes on: vendor/bsnmp/1.13/configure.ac ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/gensnmpdef/Makefile.in =================================================================== --- vendor/bsnmp/1.13/gensnmpdef/Makefile.in (nonexistent) +++ vendor/bsnmp/1.13/gensnmpdef/Makefile.in (revision 336778) @@ -0,0 +1,19 @@ +# Copyright (c) 2004 +# Hartmut Brandt +# All rights reserved. +# +# Author: Harti Brandt +# +# $Begemot: bsnmp/trunk/gensnmpdef/Makefile.in 1487 2008-12-23 19:03:33Z brandt_h $ +# + +PROG= gensnmpdef +SRCS= gensnmpdef.c +MAN1= gensnmpdef.1 + +CFLAGS+= -I/usr/local/include + +$(PROG): $(SRCS:.c=.lo) + $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ $(SRCS:.c=.lo) -lsmi + +CLEANFILES+= *.1out Property changes on: vendor/bsnmp/1.13/gensnmpdef/Makefile.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/gensnmpdef/gensnmpdef.1 =================================================================== --- vendor/bsnmp/1.13/gensnmpdef/gensnmpdef.1 (nonexistent) +++ vendor/bsnmp/1.13/gensnmpdef/gensnmpdef.1 (revision 336778) @@ -0,0 +1,85 @@ +.\" +.\" Copyright (C) 2004-2006 +.\" Hartmut Brandt. +.\" All rights reserved. +.\" +.\" Author: Harti Brandt +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Begemot: gensnmpdef.1 383 2006-05-30 07:40:49Z brandt_h $ +.\" +.Dd May 28, 2006 +.Dt GENSNMPDEF 1 +.Os +.Sh NAME +.Nm gensnmpdef +.Nd "generate a MIB description file from MIBs" +.Sh SYNOPSIS +.Nm +.Op Fl hEe +.Op Fl c Ar cut +.Ar name Op Ar ... +.Sh DESCRIPTION +The +.Nm +utility is used to create an initial MIB description file from +one or more MIBs. +The description file must be edited to be actually useful +for feeding it into +.Xr gensnmptree 1 . +.Pp +The following options are available: +.Bl -tag -width indent +.It Fl c Ar cut +Specify the number of initial sub-oids that should be omitted +from the tree in the output. +.Xr gensnmptree 1 +automatically adds 1.3.6 in front of all OIDs so the default value +of 3 is just correct in most cases. +.It Fl E +Generate typedefs for named enumerations. +These are enumerations defined via the TEXTUAL-CONVENTION macro. +The normal tree output is suppressed. +.It Fl e +Generate typedefs for unnamed enumerations. +These are enumerations defined in the SYNTAX clause of an OBJECT-TYPE macro. +The name of the enumeration is formed by appending the string +.Ql Type +to the name of the object. +The normal tree output is suppressed. +.It Fl h +Print a short help text and exit. +.El +.Pp +.Nm +does no attempt on sorting the OID tree so in case of complex and +non-standard MIBs it is necessary to sort the tree in the resulting definition +file by hand. +.Sh SEE ALSO +.Xr snmpd 1 +.Sh AUTHORS +.An Hartmut Brandt Aq harti@FreeBSD.org +.Sh BUGS +The utility is by no means bullet-proof and may fail for complex +or non-standard MIBs. +Its output is expected to be edited by hand. Property changes on: vendor/bsnmp/1.13/gensnmpdef/gensnmpdef.1 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/gensnmpdef/gensnmpdef.c =================================================================== --- vendor/bsnmp/1.13/gensnmpdef/gensnmpdef.c (nonexistent) +++ vendor/bsnmp/1.13/gensnmpdef/gensnmpdef.c (revision 336778) @@ -0,0 +1,588 @@ +/* + * Copyright (C) 2004-2006 + * Hartmut Brandt. + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: gensnmpdef.c 383 2006-05-30 07:40:49Z brandt_h $ + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static const char usgtxt[] = +"Usage: gensnmpdef [-hEe] [-c ] MIB [MIB ...]\n" +"Options:\n" +" -c specify the number of initial sub-oids to cut from the oids\n" +" -E extract named enum types. Print a typedef for all enums defined\n" +" in syntax clauses of normal objects. Suppress normal output.\n" +" -e extract unnamed enum types. Print a typedef for all enums defined\n" +" as textual conventions. Suppress normal output.\n" +" -h print this help\n" +"MIBs are searched according to the libsmi(3) search rules and can\n" +"be specified either by path or module name\n"; + +static SmiNode *last_node; +static u_int cut = 3; + +struct tdef { + char *name; + SLIST_ENTRY(tdef) link; +}; + +static SLIST_HEAD(, tdef) tdefs = SLIST_HEAD_INITIALIZER(tdefs); +static int do_typedef = 0; + +static void print_node(SmiNode *n, u_int level); + +static void +save_node(SmiNode *n) +{ + if (n != NULL) + last_node = n; +} + +static void +pindent(u_int level) +{ + if (level >= cut) + printf("%*s", (level - cut) * 2, ""); +} + +static void +print_name(SmiNode *n) +{ + char *p; + + for (p = n->name; *p != '\0'; p++) { + if (*p == '-') + printf("_"); + else + printf("%c", *p); + } +} + +static u_int +close_node(u_int n, u_int level) +{ + while (n--) { + pindent(level); + level--; + if (level >= cut) + printf(")\n"); + } + return (level); +} + +static u_int +open_node(const SmiNode *n, u_int level, SmiNode **last) +{ + SmiNode *n1; + u_int i; + + if (*last != NULL) { + for (i = 0; i < (*last)->oidlen - 1; i++) { + if (i >= n->oidlen) { + level = close_node((*last)->oidlen - + n->oidlen, level); + break; + } + if ((*last)->oid[i] != n->oid[i]) + break; + } + if (i < (*last)->oidlen - 1) + level = close_node((*last)->oidlen - 1 - i, + level - 1) + 1; + } + + while (level < n->oidlen - 1) { + if (level >= cut) { + n1 = smiGetNodeByOID(level + 1, n->oid); + if (n1 == NULL) + continue; + pindent(level); + printf("(%u", n->oid[level]); + printf(" "); + print_name(n1); + printf("\n"); + } + level++; + } + return (level); +} + +static const char *const type_names[] = { + [SMI_BASETYPE_UNKNOWN] = "UNKNOWN_TYPE", + [SMI_BASETYPE_INTEGER32] = "INTEGER", + [SMI_BASETYPE_OCTETSTRING] = "OCTETSTRING", + [SMI_BASETYPE_OBJECTIDENTIFIER] = "OID", + [SMI_BASETYPE_UNSIGNED32] = "UNSIGNED32", + [SMI_BASETYPE_INTEGER64] = "INTEGER64", + [SMI_BASETYPE_UNSIGNED64] = "UNSIGNED64", + [SMI_BASETYPE_FLOAT32] = "FLOAT32", + [SMI_BASETYPE_FLOAT64] = "FLOAT64", + [SMI_BASETYPE_FLOAT128] = "FLOAT128", + [SMI_BASETYPE_ENUM] = "ENUM", + [SMI_BASETYPE_BITS] = "BITS", +}; + +static const char *const type_map[] = { + "Gauge32", "GAUGE", + "Gauge", "GAUGE", + "TimeTicks", "TIMETICKS", + "Counter32", "COUNTER", + "Counter", "COUNTER", + "Counter64", "COUNTER64", + "Integer32", "INTEGER32", + "IpAddress", "IPADDRESS", + NULL +}; + +static void +print_enum(SmiType *t) +{ + SmiNamedNumber *nnum; + + printf(" ("); + for (nnum = smiGetFirstNamedNumber(t); nnum != NULL; + nnum = smiGetNextNamedNumber(nnum)) + printf(" %ld %s", nnum->value.value.integer32, nnum->name); + printf(" )"); +} + +static void +print_type(SmiNode *n) +{ + SmiType *type; + u_int m; + + type = smiGetNodeType(n); + assert(type != NULL); + + if (type->name != NULL) { + for (m = 0; type_map[m] != NULL; m += 2) + if (strcmp(type_map[m], type->name) == 0) { + printf("%s", type_map[m + 1]); + return; + } + } + printf("%s", type_names[type->basetype]); + + if (type->basetype == SMI_BASETYPE_ENUM || + type->basetype == SMI_BASETYPE_BITS) + print_enum(type); + + else if (type->basetype == SMI_BASETYPE_OCTETSTRING && + type->name != NULL) + printf(" | %s", type->name); +} + +static void +print_access(SmiAccess a) +{ + if (a == SMI_ACCESS_READ_ONLY) + printf(" GET"); + else if (a == SMI_ACCESS_READ_WRITE) + printf(" GET SET"); +} + +static void +print_scalar(SmiNode *n, u_int level) +{ + SmiNode *p; + + assert (n->nodekind == SMI_NODEKIND_SCALAR); + + save_node(n); + + pindent(level); + printf("(%u ", n->oid[level]); + print_name(n); + printf(" "); + print_type(n); + + /* generate the operation from the parent node name */ + p = smiGetParentNode(n); + printf(" op_%s", p->name); + + print_access(n->access); + + printf(")\n"); +} + +static void +print_notification(SmiNode *n, u_int level) +{ + + assert (n->nodekind == SMI_NODEKIND_NOTIFICATION); + + save_node(n); + + pindent(level); + printf("(%u ", n->oid[level]); + print_name(n); + printf(" OID"); + + printf(" op_%s)\n", n->name); +} + +static void +print_col(SmiNode *n, u_int level) +{ + assert (n->nodekind == SMI_NODEKIND_COLUMN); + + save_node(n); + + pindent(level); + printf("(%u ", n->oid[level]); + print_name(n); + printf(" "); + print_type(n); + print_access(n->access); + printf(")\n"); +} + +static void +print_index(SmiNode *row) +{ + SmiElement *e; + + e = smiGetFirstElement(row); + while (e != NULL) { + printf(" "); + print_type(smiGetElementNode(e)); + e = smiGetNextElement(e); + } +} + +static void +print_table(SmiNode *n, u_int level) +{ + SmiNode *row, *col, *rel; + + assert (n->nodekind == SMI_NODEKIND_TABLE); + + save_node(n); + + pindent(level); + printf("(%u ", n->oid[level]); + print_name(n); + printf("\n"); + + row = smiGetFirstChildNode(n); + if (row->nodekind != SMI_NODEKIND_ROW) + errx(1, "%s: kind %u, not row", __func__, row->nodekind); + + save_node(n); + + pindent(level + 1); + printf("(%u ", row->oid[level + 1]); + print_name(row); + printf(" :"); + + /* index */ + rel = smiGetRelatedNode(row); + switch (row->indexkind) { + + case SMI_INDEX_INDEX: + print_index(row); + break; + + case SMI_INDEX_AUGMENT: + if (rel == NULL) + errx(1, "%s: cannot find augemented table", row->name); + print_index(rel); + break; + + default: + errx(1, "%s: cannot handle index kind %u", row->name, + row->indexkind); + } + + printf(" op_%s", n->name); + printf("\n"); + + col = smiGetFirstChildNode(row); + while (col != NULL) { + print_col(col, level + 2); + col = smiGetNextChildNode(col); + } + pindent(level + 1); + printf(")\n"); + + pindent(level); + printf(")\n"); +} + +static void +print_it(SmiNode *n, u_int level) +{ + switch (n->nodekind) { + + case SMI_NODEKIND_NODE: + print_node(n, level); + break; + + case SMI_NODEKIND_SCALAR: + print_scalar(n, level); + break; + + case SMI_NODEKIND_TABLE: + print_table(n, level); + break; + + case SMI_NODEKIND_COMPLIANCE: + case SMI_NODEKIND_GROUP: + save_node(n); + break; + + case SMI_NODEKIND_NOTIFICATION: + print_notification(n, level); + break; + + default: + errx(1, "cannot handle %u nodes", n->nodekind); + } +} + +static void +print_node(SmiNode *n, u_int level) +{ + assert (n->nodekind == SMI_NODEKIND_NODE); + + save_node(n); + + pindent(level); + printf("(%u ", n->oid[level]); + print_name(n); + printf("\n"); + + n = smiGetFirstChildNode(n); + while (n != NULL) { + print_it(n, level + 1); + n = smiGetNextChildNode(n); + } + pindent(level); + printf(")\n"); +} + +static void +save_typdef(char *name) +{ + struct tdef *t; + + t = calloc(1, sizeof(struct tdef)); + if (t == NULL) + err(1, NULL); + + t->name = name; + SLIST_INSERT_HEAD(&tdefs, t, link); +} + +static void +tdefs_cleanup(void) +{ + struct tdef *t; + + while ((t = SLIST_FIRST(&tdefs)) != NULL) { + SLIST_REMOVE_HEAD(&tdefs, link); + free(t); + } +} + +static void +print_enum_typedef(SmiType *t) +{ + SmiNamedNumber *nnum; + + for (nnum = smiGetFirstNamedNumber(t); nnum != NULL; + nnum = smiGetNextNamedNumber(nnum)) { + printf("\t%ld %s\n" , nnum->value.value.integer32, nnum->name); + } +} + +static void +print_stype(SmiNode *n) +{ + SmiType *type; + struct tdef *t = NULL; + + type = smiGetNodeType(n); + assert(type != NULL); + + if (type->basetype == SMI_BASETYPE_ENUM) { + if (do_typedef == 'e' && type->name != NULL) { + SLIST_FOREACH(t, &tdefs, link) { + if (strcmp(t->name, type->name) == 0) + return; + } + save_typdef(type->name); + printf("typedef %s ENUM (\n", type->name); + } else if (do_typedef == 'E' && type->name == NULL) + printf("typedef %sType ENUM (\n", n->name); + else + return; + + print_enum_typedef(type); + printf(")\n\n"); + + } else if (type->basetype == SMI_BASETYPE_BITS) { + if (do_typedef == 'e' && type->name != NULL) { + SLIST_FOREACH(t, &tdefs, link) { + if (strcmp(t->name, type->name) == 0) + return; + } + save_typdef(type->name); + printf("typedef %s BITS (\n", type->name); + } else if (do_typedef == 'E' && type->name == NULL) + printf("typedef %sType BITS (\n", n->name); + else + return; + + print_enum_typedef(type); + printf(")\n\n"); + } +} + +static void +print_typdefs(SmiNode *n) +{ + SmiNode *p; + + p = n; + n = smiGetFirstChildNode(n); + while (n != NULL) { + switch (n->nodekind) { + case SMI_NODEKIND_SCALAR: + case SMI_NODEKIND_COLUMN: + print_stype(n); + break; + case SMI_NODEKIND_COMPLIANCE: + case SMI_NODEKIND_GROUP: + save_node(n); + return; + default: + break; + } + n = smiGetNextChildNode(n); + } + + save_node(p); +} + +int +main(int argc, char *argv[]) +{ + int opt; + int flags; + SmiModule **mods; + char *name; + SmiNode *n, *last; + u_int level; + long u; + char *end; + + smiInit(NULL); + + while ((opt = getopt(argc, argv, "c:Eeh")) != -1) + switch (opt) { + + case 'c': + errno = 0; + u = strtol(optarg, &end, 10); + if (errno != 0) + err(1, "argument to -c"); + if (*end != '\0') + err(1, "%s: not a number", optarg); + if (u < 0 || u > 5) + err(1, "%s: out of range", optarg); + cut = (u_int)u; + break; + + case 'E': + do_typedef = 'E'; + break; + + case 'e': + do_typedef = 'e'; + break; + + case 'h': + fprintf(stderr, usgtxt); + exit(0); + } + + argc -= optind; + argv += optind; + + flags = smiGetFlags(); + flags |= SMI_FLAG_ERRORS; + smiSetFlags(flags); + + mods = malloc(sizeof(mods[0]) * argc); + if (mods == NULL) + err(1, NULL); + + for (opt = 0; opt < argc; opt++) { + if ((name = smiLoadModule(argv[opt])) == NULL) + err(1, "%s: cannot load", argv[opt]); + mods[opt] = smiGetModule(name); + } + level = 0; + last = NULL; + for (opt = 0; opt < argc; opt++) { + if (mods[opt] == NULL) /* smiGetModule failed above */ + continue; + n = smiGetFirstNode(mods[opt], SMI_NODEKIND_ANY); + if (n == NULL) + continue; + for (;;) { + if (do_typedef == 0) { + level = open_node(n, level, &last); + print_it(n, level); + last = n; + } else + print_typdefs(n); + + if (last_node == NULL || + (n = smiGetNextNode(last_node, SMI_NODEKIND_ANY)) + == NULL) + break; + } + } + if (last != NULL && do_typedef == 0) + level = close_node(last->oidlen - 1, level - 1); + else if (do_typedef != 0) + tdefs_cleanup(); + + return (0); +} Property changes on: vendor/bsnmp/1.13/gensnmpdef/gensnmpdef.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/gensnmptree/Makefile.in =================================================================== --- vendor/bsnmp/1.13/gensnmptree/Makefile.in (nonexistent) +++ vendor/bsnmp/1.13/gensnmptree/Makefile.in (revision 336778) @@ -0,0 +1,19 @@ +# Copyright (c) 2001-2003 +# Fraunhofer Institute for Open Communication Systems (FhG Fokus). +# All rights reserved. +# +# Author: Harti Brandt +# +# $Begemot: bsnmp/trunk/gensnmptree/Makefile.in 1487 2008-12-23 19:03:33Z brandt_h $ +# + +PROG= gensnmptree +SRCS= gensnmptree.c +MAN1= gensnmptree.1 + +CFLAGS+= -I$(srcdir)/../lib + +$(PROG): $(SRCS:.c=.lo) + $(LIBTOOL) --mode=link $(CC) $(LDLAGS) -o $@ $(SRCS:.c=.lo) + +CLEANFILES+= *.1out Property changes on: vendor/bsnmp/1.13/gensnmptree/Makefile.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/gensnmptree/gensnmptree.1 =================================================================== --- vendor/bsnmp/1.13/gensnmptree/gensnmptree.1 (nonexistent) +++ vendor/bsnmp/1.13/gensnmptree/gensnmptree.1 (revision 336778) @@ -0,0 +1,246 @@ +.\" +.\" Copyright (c) 2001-2005 +.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus). +.\" All rights reserved. +.\" Copyright (c) 2006 +.\" Hartmut Brandt +.\" All rights reserved. +.\" +.\" Author: Harti Brandt +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Begemot: gensnmptree.1 383 2006-05-30 07:40:49Z brandt_h $ +.\" +.Dd May 26, 2006 +.Dt GENSNMPTREE 1 +.Os +.Sh NAME +.Nm gensnmptree +.Nd "generate C and header files from a MIB description file" +.Sh SYNOPSIS +.Nm +.Op Fl dEehlt +.Op Fl I Ar directory +.Op Fl i Ar infile +.Op Fl p Ar prefix +.Op Ar name Ar ... +.Sh DESCRIPTION +The +.Nm +utility is used to either generate C language tables and header files from +a MIB description or to numeric OIDs from MIB descriptions. +The first form is used only for maintaining the +.Xr bsnmpd 1 +daemon or for module writers. +The second form may be used by SNMP client program writers. +.Pp +If none of the options +.Fl e , +.Fl E +or +.Fl t +are used +.Nm +reads a MIB description from its standard input and creates two files: a +C-file +.Ar prefix Ns tree.c +containing a table used by +.Xr bsnmpd 1 +during PDU processing +and a header file +.Ar prefix Ns tree.h +containing appropriate declarations of the callback functions used in this +table, the table itself and definitions for all enums. +.Pp +The following options are available: +.Bl -tag -width ".Fl E" +.It Fl d +Switch on debugging. +.It Fl E +Extract enumerations and bit constructs. +In this mode the tool emits +a header file that contains for each type given on the command line a +C-enum definition and a preprocessor define that may be used to map +values to strings. +.It Fl e +.Nm +expects MIB variable names (only the last component) on its command line. +It reads a MIB specification from standard input and for each MIB variable +name emits three C preprocessor defines on its standard output: +.Bl -tag -width ".Va OIDLEN_ Ns Ar Name" +.It Va OIDX_ Ns Ar name +This define can be used to initialize a +.Va struct asn_oid +in the following way: +.Pp +.Dl const struct asn_oid oid_sysDescr = OIDX_sysDescr; +.It Va OIDLEN_ Ns Ar name +is the length of the OID. +.It Va OID_ Ns Ar name +is the last component of the OID. +.El +.It Fl h +Print a short help page. +.It Fl I Ar directory +Add the named directory to the include path just before the standard include +directories. +.It Fl i Ar infile +Read from the named file instead of standard input. +.It Fl l +Generate local preprocessor includes. +This is used for bootstrapping +.Xr bsnmpd 1 . +.It Fl t +Instead of normal output print the resulting tree. +.It Fl p Ar prefix +Prefix the file names and the table name with +.Ar prefix . +.El +.Sh MIBS +The syntax of the MIB description file can formally be specified as follows: +.Bd -unfilled -offset indent + file := top | top file + + top := tree | typedef | include + + tree := head elements ')' + + entry := head ':' index STRING elements ')' + + leaf := head type STRING ACCESS ')' + + column := head type ACCESS ')' + + type := BASETYPE | BASETYPE '|' subtype | enum | bits + + subtype := STRING + + enum := ENUM '(' value ')' + + bits := BITS '(' value ')' + + value := INT STRING | INT STRING value + + head := '(' INT STRING + + elements := EMPTY | elements element + + element := tree | leaf | column + + index := type | index type + + typedef := 'typedef' STRING type + + include := 'include' filespec + + filespec := '"' STRING '"' | '<' STRING '>' +.Ed +.Pp +.Ar BASETYPE +specifies a SNMP data type and may be one of +.Bl -bullet -offset indent -compact +.It +NULL +.It +INTEGER +.It +INTEGER32 (same as INTEGER) +.It +UNSIGNED32 (same as GAUGE) +.It +OCTETSTRING +.It +IPADDRESS +.It +OID +.It +TIMETICKS +.It +COUNTER +.It +GAUGE +.It +COUNTER64 +.El +.Pp +.Ar ACCESS +specifies the accessibility of the MIB variable (which operation can be +performed) and is one of +.Bl -bullet -offset indent -compact +.It +GET +.It +SET +.El +.Pp +.Ar INT +is a decimal integer and +.Ar STRING +is any string starting with a letter or underscore and consisting of +letters, digits, underscores and minuses, that is not one of the keywords. +.Pp +The +.Ar typedef +directive associates a type with a single name. +.Pp +The +.Ar include +directive is replaced by the contents of the named file. +.Sh EXAMPLES +The following MIB description describes the system group: +.Bd -literal -offset indent +include "tc.def" + +typedef AdminStatus ENUM ( + 1 up + 2 down +) + +(1 internet + (2 mgmt + (1 mibII + (1 system + (1 sysDescr OCTETSTRING op_system_group GET) + (2 sysObjectId OID op_system_group GET) + (3 sysUpTime TIMETICKS op_system_group GET) + (4 sysContact OCTETSTRING op_system_group GET SET) + (5 sysName OCTETSTRING op_system_group GET SET) + (6 sysLocation OCTETSTRING op_system_group GET SET) + (7 sysServices INTEGER op_system_group GET) + (8 sysORLastChange TIMETICKS op_system_group GET) + (9 sysORTable + (1 sysOREntry : INTEGER op_or_table + (1 sysORIndex INTEGER) + (2 sysORID OID GET) + (3 sysORDescr OCTETSTRING GET) + (4 sysORUpTime TIMETICKS GET) + )) + ) + ) + ) +) +.Ed +.Sh SEE ALSO +.Xr bsnmpd 1 +.Sh AUTHORS +.An Hartmut Brandt Aq harti@FreeBSD.org Property changes on: vendor/bsnmp/1.13/gensnmptree/gensnmptree.1 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/gensnmptree/gensnmptree.c =================================================================== --- vendor/bsnmp/1.13/gensnmptree/gensnmptree.c (nonexistent) +++ vendor/bsnmp/1.13/gensnmptree/gensnmptree.c (revision 336778) @@ -0,0 +1,1737 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Copyright (c) 2004-2006,2018 + * Hartmut Brandt. + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: gensnmptree.c 383 2006-05-30 07:40:49Z brandt_h $ + * + * Generate OID table from table description. + * + * Syntax is: + * --------- + * file := top | top file + * + * top := tree | typedef | include + * + * tree := head elements ')' + * + * entry := head ':' index STRING elements ')' + * + * leaf := head type STRING ACCESS ')' + * + * column := head type ACCESS ')' + * + * type := BASETYPE | BASETYPE '|' subtype | enum | bits + * + * subtype := STRING + * + * enum := ENUM '(' value ')' + * + * bits := BITS '(' value ')' + * + * value := optminus INT STRING | optminus INT STRING value + * + * optminus := '-' | EMPTY + * + * head := '(' INT STRING + * + * elements := EMPTY | elements element + * + * element := tree | leaf | column + * + * index := type | index type + * + * typedef := 'typedef' STRING type + * + * include := 'include' filespec + * + * filespec := '"' STRING '"' | '<' STRING '>' + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_ERR_H +#include +#endif +#include +#include "support.h" +#include "asn1.h" +#include "snmp.h" +#include "snmpagent.h" + +/* + * Constant prefix for all OIDs + */ +static const asn_subid_t prefix[] = { 1, 3, 6 }; +#define PREFIX_LEN (sizeof(prefix) / sizeof(prefix[0])) + +u_int tree_size; +static const char *file_prefix = ""; + +/* if true generate local include paths */ +static int localincs = 0; + +/* if true print tokens */ +static int debug; + +static const char usgtxt[] = "\ +Generate SNMP tables.\n\ +usage: gensnmptree [-dEeFfhlt] [-I directory] [-i infile] [-p prefix]\n\ + [name]...\n\ +options:\n\ + -d debug mode\n\ + -E extract the named or all enums and bits only\n\ + -e extract the named oids or enums\n\ + -F generate functions for -E into a .c file\n\ + -f generate functions for -E into the header\n\ + -h print this info\n\ + -I directory add directory to include path\n\ + -i ifile read from the named file instead of stdin\n\ + -l generate local include directives\n\ + -p prefix prepend prefix to file and variable names\n\ + -t generated a .def file\n\ +"; + +/* + * A node in the OID tree + */ +enum ntype { + NODE_LEAF = 1, + NODE_TREE, + NODE_ENTRY, + NODE_COLUMN +}; + +enum { + FL_GET = 0x01, + FL_SET = 0x02, +}; + +struct node; +TAILQ_HEAD(node_list, node); + +struct node { + enum ntype type; + asn_subid_t id; /* last element of OID */ + char *name; /* name of node */ + TAILQ_ENTRY(node) link; + u_int lno; /* starting line number */ + u_int flags; /* allowed operations */ + + union { + struct tree { + struct node_list subs; + } tree; + + struct entry { + uint32_t index; /* index for table entry */ + char *func; /* function for tables */ + struct node_list subs; + } entry; + + struct leaf { + enum snmp_syntax syntax; /* syntax for this leaf */ + char *func; /* function name */ + } leaf; + + struct column { + enum snmp_syntax syntax; /* syntax for this column */ + } column; + } u; +}; + +struct func { + const char *name; + LIST_ENTRY(func) link; +}; + +static LIST_HEAD(, func) funcs = LIST_HEAD_INITIALIZER(funcs); + +struct enums { + const char *name; + long value; + TAILQ_ENTRY(enums) link; +}; + +struct type { + const char *name; + const char *from_fname; + u_int from_lno; + u_int syntax; + int is_enum; + int is_bits; + TAILQ_HEAD(, enums) enums; + LIST_ENTRY(type) link; +}; + +static LIST_HEAD(, type) types = LIST_HEAD_INITIALIZER(types); + +static void report(const char *, ...) __dead2 __printflike(1, 2); +static void report_node(const struct node *, const char *, ...) + __dead2 __printflike(2, 3); + +/************************************************************ + * + * Allocate memory and panic just in the case... + */ +static void * +xalloc(size_t size) +{ + void *ptr; + + if ((ptr = malloc(size)) == NULL) + err(1, "allocing %zu bytes", size); + + return (ptr); +} + +static char * +savestr(const char *s) +{ + + if (s == NULL) + return (NULL); + return (strcpy(xalloc(strlen(s) + 1), s)); +} + +/************************************************************ + * + * Input stack + */ +struct input { + FILE *fp; + u_int lno; + char *fname; + char *path; + LIST_ENTRY(input) link; +}; +static LIST_HEAD(, input) inputs = LIST_HEAD_INITIALIZER(inputs); +static struct input *input = NULL; + +#define MAX_PATHS 100 +static u_int npaths = 2; +static u_int stdpaths = 2; +static const char *paths[MAX_PATHS + 1] = { + "/usr/share/snmp/defs", + "/usr/local/share/snmp/defs", + NULL +}; + +static int pbchar = -1; + +static void +path_new(const char *path) +{ + if (npaths >= MAX_PATHS) + report("too many -I directives"); + memmove(&paths[npaths - stdpaths + 1], &paths[npaths - stdpaths], + sizeof(path[0]) * stdpaths); + paths[npaths - stdpaths] = savestr(path); + npaths++; +} + +static void +input_new(FILE *fp, const char *path, const char *fname) +{ + struct input *ip; + + ip = xalloc(sizeof(*ip)); + ip->fp = fp; + ip->lno = 1; + ip->fname = savestr(fname); + ip->path = savestr(path); + LIST_INSERT_HEAD(&inputs, ip, link); + + input = ip; +} + +static void +input_close(void) +{ + + if (input == NULL) + return; + fclose(input->fp); + free(input->fname); + free(input->path); + LIST_REMOVE(input, link); + free(input); + + input = LIST_FIRST(&inputs); +} + +static FILE * +tryopen(const char *path, const char *fname) +{ + char *fn; + FILE *fp; + + if (path == NULL) + fn = savestr(fname); + else { + fn = xalloc(strlen(path) + strlen(fname) + 2); + sprintf(fn, "%s/%s", path, fname); + } + fp = fopen(fn, "r"); + free(fn); + return (fp); +} + +static void +input_fopen(const char *fname, int loc) +{ + FILE *fp; + char *path; + u_int p; + + if (fname[0] == '/') { + if ((fp = tryopen(NULL, fname)) != NULL) { + input_new(fp, NULL, fname); + return; + } + + } else { + if (loc) { + if (input == NULL) + path = NULL; + else + path = input->path; + + if ((fp = tryopen(path, fname)) != NULL) { + input_new(fp, NULL, fname); + return; + } + } + + for (p = 0; paths[p] != NULL; p++) + if ((fp = tryopen(paths[p], fname)) != NULL) { + input_new(fp, paths[p], fname); + return; + } + } + report("cannot open '%s'", fname); +} + +static int +tgetc(void) +{ + int c; + + if (pbchar != -1) { + c = pbchar; + pbchar = -1; + return (c); + } + + for (;;) { + if (input == NULL) + return (EOF); + + if ((c = getc(input->fp)) != EOF) + return (c); + + input_close(); + } +} + +static void +tungetc(int c) +{ + + if (pbchar != -1) + abort(); + pbchar = c; +} + +/************************************************************ + * + * Parsing input + */ +enum tok { + TOK_EOF = 0200, /* end-of-file seen */ + TOK_NUM, /* number */ + TOK_STR, /* string */ + TOK_ACCESS, /* access operator */ + TOK_TYPE, /* type operator */ + TOK_ENUM, /* enum token (kind of a type) */ + TOK_TYPEDEF, /* typedef directive */ + TOK_DEFTYPE, /* defined type */ + TOK_INCLUDE, /* include directive */ + TOK_FILENAME, /* filename ("foo.bar" or ) */ + TOK_BITS, /* bits token (kind of a type) */ +}; + +static const struct { + const char *str; + enum tok tok; + u_int val; +} keywords[] = { + { "GET", TOK_ACCESS, FL_GET }, + { "SET", TOK_ACCESS, FL_SET }, + { "NULL", TOK_TYPE, SNMP_SYNTAX_NULL }, + { "INTEGER", TOK_TYPE, SNMP_SYNTAX_INTEGER }, + { "INTEGER32", TOK_TYPE, SNMP_SYNTAX_INTEGER }, + { "UNSIGNED32", TOK_TYPE, SNMP_SYNTAX_GAUGE }, + { "OCTETSTRING", TOK_TYPE, SNMP_SYNTAX_OCTETSTRING }, + { "IPADDRESS", TOK_TYPE, SNMP_SYNTAX_IPADDRESS }, + { "OID", TOK_TYPE, SNMP_SYNTAX_OID }, + { "TIMETICKS", TOK_TYPE, SNMP_SYNTAX_TIMETICKS }, + { "COUNTER", TOK_TYPE, SNMP_SYNTAX_COUNTER }, + { "GAUGE", TOK_TYPE, SNMP_SYNTAX_GAUGE }, + { "COUNTER64", TOK_TYPE, SNMP_SYNTAX_COUNTER64 }, + { "ENUM", TOK_ENUM, SNMP_SYNTAX_INTEGER }, + { "BITS", TOK_BITS, SNMP_SYNTAX_OCTETSTRING }, + { "typedef", TOK_TYPEDEF, 0 }, + { "include", TOK_INCLUDE, 0 }, + { NULL, 0, 0 } +}; + +/* arbitrary upper limit on node names and function names */ +#define MAXSTR 1000 +static char str[MAXSTR]; +static u_long val; /* integer values */ +static int saved_token = -1; + +/* + * Report an error and exit. + */ +static void +report(const char *fmt, ...) +{ + va_list ap; + int c; + + va_start(ap, fmt); + fprintf(stderr, "line %u: ", input->lno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + fprintf(stderr, "context: \""); + while ((c = tgetc()) != EOF && c != '\n') + fprintf(stderr, "%c", c); + fprintf(stderr, "\n"); + va_end(ap); + exit(1); +} +static void +report_node(const struct node *np, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + fprintf(stderr, "line %u, node %s: ", np->lno, np->name); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(1); +} + +/* + * Return a fresh copy of the string constituting the current token. + */ +static char * +savetok(void) +{ + return (savestr(str)); +} + +/* + * Get the next token from input. + */ +static int +gettoken_internal(void) +{ + int c; + struct type *t; + + if (saved_token != -1) { + c = saved_token; + saved_token = -1; + return (c); + } + + again: + /* + * Skip any whitespace before the next token + */ + while ((c = tgetc()) != EOF) { + if (c == '\n') + input->lno++; + if (!isspace(c)) + break; + } + if (c == EOF) + return (TOK_EOF); + if (!isascii(c)) + report("unexpected character %#2x", (u_int)c); + + /* + * Skip comments + */ + if (c == '#') { + while ((c = tgetc()) != EOF) { + if (c == '\n') { + input->lno++; + goto again; + } + } + report("unexpected EOF in comment"); + } + + /* + * Single character tokens + */ + if (strchr("():|-", c) != NULL) + return (c); + + if (c == '"' || c == '<') { + int end = c; + size_t n = 0; + + val = 1; + if (c == '<') { + val = 0; + end = '>'; + } + + while ((c = tgetc()) != EOF) { + if (c == end) + break; + if (n == sizeof(str) - 1) { + str[n++] = '\0'; + report("filename too long '%s...'", str); + } + str[n++] = c; + } + str[n++] = '\0'; + return (TOK_FILENAME); + } + + /* + * Sort out numbers + */ + if (isdigit(c)) { + size_t n = 0; + str[n++] = c; + while ((c = tgetc()) != EOF) { + if (!isdigit(c)) { + tungetc(c); + break; + } + if (n == sizeof(str) - 1) { + str[n++] = '\0'; + report("number too long '%s...'", str); + } + str[n++] = c; + } + str[n++] = '\0'; + sscanf(str, "%lu", &val); + return (TOK_NUM); + } + + /* + * So that has to be a string. + */ + if (isalpha(c) || c == '_') { + size_t n = 0; + str[n++] = c; + while ((c = tgetc()) != EOF) { + if (!isalnum(c) && c != '_' && c != '-') { + tungetc(c); + break; + } + if (n == sizeof(str) - 1) { + str[n++] = '\0'; + report("string too long '%s...'", str); + } + str[n++] = c; + } + str[n++] = '\0'; + + /* + * Keywords + */ + for (c = 0; keywords[c].str != NULL; c++) + if (strcmp(keywords[c].str, str) == 0) { + val = keywords[c].val; + return (keywords[c].tok); + } + + LIST_FOREACH(t, &types, link) { + if (strcmp(t->name, str) == 0) { + val = t->syntax; + return (TOK_DEFTYPE); + } + } + return (TOK_STR); + } + if (isprint(c)) + errx(1, "%u: unexpected character '%c'", input->lno, c); + else + errx(1, "%u: unexpected character 0x%02x", input->lno, + (u_int)c); +} +static int +gettoken(void) +{ + int tok = gettoken_internal(); + + if (debug) { + switch (tok) { + + case TOK_EOF: + fprintf(stderr, "EOF "); + break; + + case TOK_NUM: + fprintf(stderr, "NUM(%lu) ", val); + break; + + case TOK_STR: + fprintf(stderr, "STR(%s) ", str); + break; + + case TOK_ACCESS: + fprintf(stderr, "ACCESS(%lu) ", val); + break; + + case TOK_TYPE: + fprintf(stderr, "TYPE(%lu) ", val); + break; + + case TOK_ENUM: + fprintf(stderr, "ENUM "); + break; + + case TOK_BITS: + fprintf(stderr, "BITS "); + break; + + case TOK_TYPEDEF: + fprintf(stderr, "TYPEDEF "); + break; + + case TOK_DEFTYPE: + fprintf(stderr, "DEFTYPE(%s,%lu) ", str, val); + break; + + case TOK_INCLUDE: + fprintf(stderr, "INCLUDE "); + break; + + case TOK_FILENAME: + fprintf(stderr, "FILENAME "); + break; + + default: + if (tok < TOK_EOF) { + if (isprint(tok)) + fprintf(stderr, "'%c' ", tok); + else if (tok == '\n') + fprintf(stderr, "\n"); + else + fprintf(stderr, "%02x ", tok); + } else + abort(); + break; + } + } + return (tok); +} + +/** + * Pushback a token + */ +static void +pushback(enum tok tok) +{ + + if (saved_token != -1) + abort(); + saved_token = tok; +} + +/* + * Create a new type + */ +static struct type * +make_type(const char *s) +{ + struct type *t; + + t = xalloc(sizeof(*t)); + t->name = savestr(s); + t->is_enum = 0; + t->syntax = SNMP_SYNTAX_NULL; + t->from_fname = savestr(input->fname); + t->from_lno = input->lno; + TAILQ_INIT(&t->enums); + LIST_INSERT_HEAD(&types, t, link); + + return (t); +} + +/* + * Parse a type. We've seen the ENUM or type keyword already. Leave next + * token. + */ +static u_int +parse_type(enum tok *tok, struct type *t, const char *vname) +{ + u_int syntax; + struct enums *e; + + syntax = val; + + if (*tok == TOK_ENUM || *tok == TOK_BITS) { + if (t == NULL && vname != NULL) { + t = make_type(vname); + t->is_enum = (*tok == TOK_ENUM); + t->is_bits = (*tok == TOK_BITS); + t->syntax = syntax; + } + if (gettoken() != '(') + report("'(' expected after ENUM"); + + if ((*tok = gettoken()) == TOK_EOF) + report("unexpected EOF in ENUM"); + do { + e = NULL; + if (t != NULL) { + e = xalloc(sizeof(*e)); + } + if (*tok == '-') { + if ((*tok = gettoken()) == TOK_EOF) + report("unexpected EOF in ENUM"); + e->value = -(long)val; + } else + e->value = val; + + if (*tok != TOK_NUM) + report("need value for ENUM/BITS"); + if (gettoken() != TOK_STR) + report("need string in ENUM/BITS"); + e->name = savetok(); + TAILQ_INSERT_TAIL(&t->enums, e, link); + if ((*tok = gettoken()) == TOK_EOF) + report("unexpected EOF in ENUM/BITS"); + } while (*tok != ')'); + *tok = gettoken(); + + } else if (*tok == TOK_DEFTYPE) { + *tok = gettoken(); + + } else { + if ((*tok = gettoken()) == '|') { + if (gettoken() != TOK_STR) + report("subtype expected after '|'"); + *tok = gettoken(); + } + } + + return (syntax); +} + +/* + * Parse the next node (complete with all subnodes) + */ +static struct node * +parse(enum tok tok) +{ + struct node *node; + struct node *sub; + u_int index_count; + + node = xalloc(sizeof(struct node)); + node->lno = input->lno; + node->flags = 0; + + if (tok != '(') + report("'(' expected at begin of node"); + if (gettoken() != TOK_NUM) + report("node id expected after opening '('"); + if (val > ASN_MAXID) + report("subid too large '%lu'", val); + node->id = (asn_subid_t)val; + if (gettoken() != TOK_STR) + report("node name expected after '(' ID"); + node->name = savetok(); + + if ((tok = gettoken()) == TOK_TYPE || tok == TOK_DEFTYPE || + tok == TOK_ENUM || tok == TOK_BITS) { + /* LEAF or COLUM */ + u_int syntax = parse_type(&tok, NULL, node->name); + + if (tok == TOK_STR) { + /* LEAF */ + node->type = NODE_LEAF; + node->u.leaf.func = savetok(); + node->u.leaf.syntax = syntax; + tok = gettoken(); + } else { + /* COLUMN */ + node->type = NODE_COLUMN; + node->u.column.syntax = syntax; + } + + while (tok != ')') { + if (tok != TOK_ACCESS) + report("access keyword or ')' expected"); + node->flags |= (u_int)val; + tok = gettoken(); + } + + } else if (tok == ':') { + /* ENTRY */ + node->type = NODE_ENTRY; + TAILQ_INIT(&node->u.entry.subs); + + index_count = 0; + node->u.entry.index = 0; + tok = gettoken(); + while (tok == TOK_TYPE || tok == TOK_DEFTYPE || + tok == TOK_ENUM || tok == TOK_BITS) { + u_int syntax = parse_type(&tok, NULL, node->name); + if (index_count++ == SNMP_INDEXES_MAX) + report("too many table indexes"); + node->u.entry.index |= + syntax << (SNMP_INDEX_SHIFT * index_count); + } + node->u.entry.index |= index_count; + if (index_count == 0) + report("need at least one index"); + if (tok != TOK_STR) + report("function name expected"); + + node->u.entry.func = savetok(); + + tok = gettoken(); + + while (tok != ')') { + sub = parse(tok); + TAILQ_INSERT_TAIL(&node->u.entry.subs, sub, link); + tok = gettoken(); + } + + } else { + /* subtree */ + node->type = NODE_TREE; + TAILQ_INIT(&node->u.tree.subs); + + while (tok != ')') { + sub = parse(tok); + TAILQ_INSERT_TAIL(&node->u.tree.subs, sub, link); + tok = gettoken(); + } + } + return (node); +} + +/* + * Parse a top level element. Return the tree if it was a tree, NULL + * otherwise. + */ +static struct node * +parse_top(enum tok tok) +{ + struct type *t; + + if (tok == '(') + return (parse(tok)); + + if (tok == TOK_TYPEDEF) { + if (gettoken() != TOK_STR) + report("type name expected after typedef"); + + t = make_type(str); + + tok = gettoken(); + t->is_enum = (tok == TOK_ENUM); + t->is_bits = (tok == TOK_BITS); + t->syntax = parse_type(&tok, t, NULL); + pushback(tok); + + return (NULL); + } + + if (tok == TOK_INCLUDE) { + if (gettoken() != TOK_FILENAME) + report("filename expected in include directive"); + + input_fopen(str, val); + return (NULL); + } + + report("'(' or 'typedef' expected"); +} + +/* + * Generate the C-code table part for one node. + */ +static void +gen_node(FILE *fp, struct node *np, struct asn_oid *oid, u_int idx, + const char *func) +{ + u_int n; + struct node *sub; + u_int syntax; + + if (oid->len == ASN_MAXOIDLEN) + report_node(np, "OID too long"); + oid->subs[oid->len++] = np->id; + + if (np->type == NODE_TREE) { + TAILQ_FOREACH(sub, &np->u.tree.subs, link) + gen_node(fp, sub, oid, 0, NULL); + oid->len--; + return; + } + if (np->type == NODE_ENTRY) { + TAILQ_FOREACH(sub, &np->u.entry.subs, link) + gen_node(fp, sub, oid, np->u.entry.index, + np->u.entry.func); + oid->len--; + return; + } + + /* leaf or column */ + if ((np->flags & (FL_GET|FL_SET)) == 0) { + oid->len--; + return; + } + + fprintf(fp, " {{ %u, {", oid->len); + for (n = 0; n < oid->len; n++) + fprintf(fp, " %u,", oid->subs[n]); + fprintf(fp, " }}, \"%s\", ", np->name); + + if (np->type == NODE_COLUMN) { + syntax = np->u.column.syntax; + fprintf(fp, "SNMP_NODE_COLUMN, "); + } else { + syntax = np->u.leaf.syntax; + fprintf(fp, "SNMP_NODE_LEAF, "); + } + + switch (syntax) { + + case SNMP_SYNTAX_NULL: + fprintf(fp, "SNMP_SYNTAX_NULL, "); + break; + + case SNMP_SYNTAX_INTEGER: + fprintf(fp, "SNMP_SYNTAX_INTEGER, "); + break; + + case SNMP_SYNTAX_OCTETSTRING: + fprintf(fp, "SNMP_SYNTAX_OCTETSTRING, "); + break; + + case SNMP_SYNTAX_IPADDRESS: + fprintf(fp, "SNMP_SYNTAX_IPADDRESS, "); + break; + + case SNMP_SYNTAX_OID: + fprintf(fp, "SNMP_SYNTAX_OID, "); + break; + + case SNMP_SYNTAX_TIMETICKS: + fprintf(fp, "SNMP_SYNTAX_TIMETICKS, "); + break; + + case SNMP_SYNTAX_COUNTER: + fprintf(fp, "SNMP_SYNTAX_COUNTER, "); + break; + + case SNMP_SYNTAX_GAUGE: + fprintf(fp, "SNMP_SYNTAX_GAUGE, "); + break; + + case SNMP_SYNTAX_COUNTER64: + fprintf(fp, "SNMP_SYNTAX_COUNTER64, "); + break; + + case SNMP_SYNTAX_NOSUCHOBJECT: + case SNMP_SYNTAX_NOSUCHINSTANCE: + case SNMP_SYNTAX_ENDOFMIBVIEW: + abort(); + } + + if (np->type == NODE_COLUMN) + fprintf(fp, "%s, ", func); + else + fprintf(fp, "%s, ", np->u.leaf.func); + + fprintf(fp, "0"); + if (np->flags & FL_SET) + fprintf(fp, "|SNMP_NODE_CANSET"); + fprintf(fp, ", %#x, NULL, NULL },\n", idx); + oid->len--; + return; +} + +/* + * Generate the header file with the function declarations. + */ +static void +gen_header(FILE *fp, struct node *np, u_int oidlen, const char *func) +{ + char f[MAXSTR + 4]; + struct node *sub; + struct func *ptr; + + oidlen++; + if (np->type == NODE_TREE) { + TAILQ_FOREACH(sub, &np->u.tree.subs, link) + gen_header(fp, sub, oidlen, NULL); + return; + } + if (np->type == NODE_ENTRY) { + TAILQ_FOREACH(sub, &np->u.entry.subs, link) + gen_header(fp, sub, oidlen, np->u.entry.func); + return; + } + + if((np->flags & (FL_GET|FL_SET)) == 0) + return; + + if (np->type == NODE_COLUMN) { + if (func == NULL) + errx(1, "column without function (%s) - probably " + "outside of a table", np->name); + sprintf(f, "%s", func); + } else + sprintf(f, "%s", np->u.leaf.func); + + LIST_FOREACH(ptr, &funcs, link) + if (strcmp(ptr->name, f) == 0) + break; + + if (ptr == NULL) { + ptr = xalloc(sizeof(*ptr)); + ptr->name = savestr(f); + LIST_INSERT_HEAD(&funcs, ptr, link); + + fprintf(fp, "int %s(struct snmp_context *, " + "struct snmp_value *, u_int, u_int, " + "enum snmp_op);\n", f); + } + + fprintf(fp, "# define LEAF_%s %u\n", np->name, np->id); +} + +/* + * Generate the OID table. + */ +static void +gen_table(FILE *fp, struct node *node) +{ + struct asn_oid oid; + + fprintf(fp, "#include \n"); + fprintf(fp, "#include \n"); +#ifdef HAVE_STDINT_H + fprintf(fp, "#include \n"); +#endif + if (localincs) { + fprintf(fp, "#include \"asn1.h\"\n"); + fprintf(fp, "#include \"snmp.h\"\n"); + fprintf(fp, "#include \"snmpagent.h\"\n"); + } else { + fprintf(fp, "#include \n"); + fprintf(fp, "#include \n"); + fprintf(fp, "#include \n"); + } + fprintf(fp, "#include \"%stree.h\"\n", file_prefix); + fprintf(fp, "\n"); + + fprintf(fp, "const struct snmp_node %sctree[] = {\n", file_prefix); + + oid.len = PREFIX_LEN; + memcpy(oid.subs, prefix, sizeof(prefix)); + gen_node(fp, node, &oid, 0, NULL); + + fprintf(fp, "};\n\n"); +} + +static void +print_syntax(u_int syntax) +{ + u_int i; + + for (i = 0; keywords[i].str != NULL; i++) + if (keywords[i].tok == TOK_TYPE && + keywords[i].val == syntax) { + printf(" %s", keywords[i].str); + return; + } + abort(); +} + +/* + * Generate a tree definition file + */ +static void +gen_tree(const struct node *np, int level) +{ + const struct node *sp; + u_int i; + + printf("%*s(%u %s", 2 * level, "", np->id, np->name); + + switch (np->type) { + + case NODE_LEAF: + print_syntax(np->u.leaf.syntax); + printf(" %s%s%s)\n", np->u.leaf.func, + (np->flags & FL_GET) ? " GET" : "", + (np->flags & FL_SET) ? " SET" : ""); + break; + + case NODE_TREE: + if (TAILQ_EMPTY(&np->u.tree.subs)) { + printf(")\n"); + } else { + printf("\n"); + TAILQ_FOREACH(sp, &np->u.tree.subs, link) + gen_tree(sp, level + 1); + printf("%*s)\n", 2 * level, ""); + } + break; + + case NODE_ENTRY: + printf(" :"); + + for (i = 0; i < SNMP_INDEX_COUNT(np->u.entry.index); i++) + print_syntax(SNMP_INDEX(np->u.entry.index, i)); + printf(" %s\n", np->u.entry.func); + TAILQ_FOREACH(sp, &np->u.entry.subs, link) + gen_tree(sp, level + 1); + printf("%*s)\n", 2 * level, ""); + break; + + case NODE_COLUMN: + print_syntax(np->u.column.syntax); + printf("%s%s)\n", (np->flags & FL_GET) ? " GET" : "", + (np->flags & FL_SET) ? " SET" : ""); + break; + } +} + +static int +extract(FILE *fp, const struct node *np, struct asn_oid *oid, const char *obj, + const struct asn_oid *idx, const char *iname) +{ + struct node *sub; + u_long n; + + if (oid->len == ASN_MAXOIDLEN) + report_node(np, "OID too long"); + oid->subs[oid->len++] = np->id; + + if (strcmp(obj, np->name) == 0) { + if (oid->len + idx->len >= ASN_MAXOIDLEN) + report_node(np, "OID too long"); + fprintf(fp, "#define OID_%s%s\t%u\n", np->name, + iname ? iname : "", np->id); + fprintf(fp, "#define OIDLEN_%s%s\t%u\n", np->name, + iname ? iname : "", oid->len + idx->len); + fprintf(fp, "#define OIDX_%s%s\t{ %u, {", np->name, + iname ? iname : "", oid->len + idx->len); + for (n = 0; n < oid->len; n++) + fprintf(fp, " %u,", oid->subs[n]); + for (n = 0; n < idx->len; n++) + fprintf(fp, " %u,", idx->subs[n]); + fprintf(fp, " } }\n"); + return (0); + } + + if (np->type == NODE_TREE) { + TAILQ_FOREACH(sub, &np->u.tree.subs, link) + if (!extract(fp, sub, oid, obj, idx, iname)) + return (0); + } else if (np->type == NODE_ENTRY) { + TAILQ_FOREACH(sub, &np->u.entry.subs, link) + if (!extract(fp, sub, oid, obj, idx, iname)) + return (0); + } + oid->len--; + return (1); +} + +static int +gen_extract(FILE *fp, const struct node *root, char *object) +{ + struct asn_oid oid; + struct asn_oid idx; + char *s, *e, *end, *iname; + u_long ul; + int ret; + + /* look whether the object to extract has an index part */ + idx.len = 0; + iname = NULL; + s = strchr(object, '.'); + if (s != NULL) { + iname = malloc(strlen(s) + 1); + if (iname == NULL) + err(1, "cannot allocated index"); + + strcpy(iname, s); + for (e = iname; *e != '\0'; e++) + if (*e == '.') + *e = '_'; + + *s++ = '\0'; + while (s != NULL) { + if (*s == '\0') + errx(1, "bad index syntax"); + if ((e = strchr(s, '.')) != NULL) + *e++ = '\0'; + + errno = 0; + ul = strtoul(s, &end, 0); + if (*end != '\0') + errx(1, "bad index syntax '%s'", end); + if (errno != 0) + err(1, "bad index syntax"); + + if (idx.len == ASN_MAXOIDLEN) + errx(1, "index oid too large"); + idx.subs[idx.len++] = ul; + + s = e; + } + } + + oid.len = PREFIX_LEN; + memcpy(oid.subs, prefix, sizeof(prefix)); + ret = extract(fp, root, &oid, object, &idx, iname); + if (iname != NULL) + free(iname); + + return (ret); +} + + +static void +check_sub_order(const struct node *np, const struct node_list *subs) +{ + int first; + const struct node *sub; + asn_subid_t maxid = 0; + + /* ensure, that subids are ordered */ + first = 1; + TAILQ_FOREACH(sub, subs, link) { + if (!first && sub->id <= maxid) + report_node(np, "subids not ordered at %s", sub->name); + maxid = sub->id; + first = 0; + } +} + +/* + * Do some sanity checks on the tree definition and do some computations. + */ +static void +check_tree(struct node *np) +{ + struct node *sub; + + if (np->type == NODE_LEAF || np->type == NODE_COLUMN) { + if ((np->flags & (FL_GET|FL_SET)) != 0) + tree_size++; + return; + } + + if (np->type == NODE_ENTRY) { + check_sub_order(np, &np->u.entry.subs); + + /* ensure all subnodes are columns */ + TAILQ_FOREACH(sub, &np->u.entry.subs, link) { + if (sub->type != NODE_COLUMN) + report_node(np, "entry subnode '%s' is not " + "a column", sub->name); + check_tree(sub); + } + } else { + check_sub_order(np, &np->u.tree.subs); + + TAILQ_FOREACH(sub, &np->u.tree.subs, link) + check_tree(sub); + } +} + +static void +merge_subs(struct node_list *s1, struct node_list *s2) +{ + struct node *n1, *n2; + + while (!TAILQ_EMPTY(s2)) { + n2 = TAILQ_FIRST(s2); + TAILQ_REMOVE(s2, n2, link); + + TAILQ_FOREACH(n1, s1, link) + if (n1->id >= n2->id) + break; + if (n1 == NULL) + TAILQ_INSERT_TAIL(s1, n2, link); + else if (n1->id > n2->id) + TAILQ_INSERT_BEFORE(n1, n2, link); + else { + if (n1->type == NODE_TREE && n2->type == NODE_TREE) { + if (strcmp(n1->name, n2->name) != 0) + errx(1, "trees to merge must have " + "same name '%s' '%s'", n1->name, + n2->name); + merge_subs(&n1->u.tree.subs, &n2->u.tree.subs); + free(n2); + } else if (n1->type == NODE_ENTRY && + n2->type == NODE_ENTRY) { + if (strcmp(n1->name, n2->name) != 0) + errx(1, "entries to merge must have " + "same name '%s' '%s'", n1->name, + n2->name); + if (n1->u.entry.index != n2->u.entry.index) + errx(1, "entries to merge must have " + "same index '%s'", n1->name); + if (strcmp(n1->u.entry.func, + n2->u.entry.func) != 0) + errx(1, "entries to merge must have " + "same op '%s'", n1->name); + merge_subs(&n1->u.entry.subs, + &n2->u.entry.subs); + free(n2); + } else + errx(1, "entities to merge must be both " + "trees or both entries: %s, %s", + n1->name, n2->name); + } + } +} + +static void +merge(struct node **root, struct node *t) +{ + + if (*root == NULL) { + *root = t; + return; + } + if (t == NULL) + return; + + /* both must be trees */ + if ((*root)->type != NODE_TREE) + errx(1, "root is not a tree"); + if (t->type != NODE_TREE) + errx(1, "can merge only with tree"); + if ((*root)->id != t->id) + errx(1, "trees to merge must have same id"); + + merge_subs(&(*root)->u.tree.subs, &t->u.tree.subs); +} + +static void +unminus(FILE *fp, const char *s) +{ + + while (*s != '\0') { + if (*s == '-') + fprintf(fp, "_"); + else + fprintf(fp, "%c", *s); + s++; + } +} + +/** + * Generate a definition for the enum packed into a guard against multiple + * definitions. + * + * \param fp file to write definition to + * \param t type + */ +static void +gen_enum(FILE *fp, const struct type *t) +{ + const struct enums *e; + long min = LONG_MAX; + + fprintf(fp, "\n"); + fprintf(fp, "#ifndef %s_defined__\n", t->name); + fprintf(fp, "#define %s_defined__\n", t->name); + fprintf(fp, "/*\n"); + fprintf(fp, " * From %s:%u\n", t->from_fname, t->from_lno); + fprintf(fp, " */\n"); + fprintf(fp, "enum %s {\n", t->name); + TAILQ_FOREACH(e, &t->enums, link) { + fprintf(fp, "\t%s_", t->name); + unminus(fp, e->name); + fprintf(fp, " = %ld,\n", e->value); + if (e->value < min) + min = e->value; + } + fprintf(fp, "};\n"); + fprintf(fp, "#define STROFF_%s %ld\n", t->name, min); + fprintf(fp, "#define STRING_%s \\\n", t->name); + TAILQ_FOREACH(e, &t->enums, link) { + fprintf(fp, "\t[%ld] = \"%s_", e->value - min, t->name); + unminus(fp, e->name); + fprintf(fp, "\",\\\n"); + } + fprintf(fp, "\n"); + fprintf(fp, "#endif /* %s_defined__ */\n", t->name); +} + +/** + * Generate helper functions for an enum. + * + * We always generate a switch statement for the isok function. The compiler + * optimizes this into range checks if possible. + * + * \param fp file to write to + * \param t type + * \param ccode generate externally visible non-inline functions + */ +static void +gen_enum_funcs(FILE *fp, const struct type *t, int ccode) +{ + fprintf(fp, "\n"); + + if (!ccode) + fprintf(fp, "static inline "); + fprintf(fp, "int\n"); + fprintf(fp, "isok_%s(enum %s s)\n", t->name, t->name); + fprintf(fp, "{\n"); + fprintf(fp, " switch (s) {\n"); + + const struct enums *e; + TAILQ_FOREACH(e, &t->enums, link) { + fprintf(fp, "\t case %s_", t->name); + unminus(fp, e->name); + fprintf(fp, ":\n"); + } + + fprintf(fp, " return (1);\n"); + fprintf(fp, " }\n"); + fprintf(fp, " return (0);\n"); + fprintf(fp, "}\n\n"); + + if (!ccode) + fprintf(fp, "static inline "); + fprintf(fp, "const char *\n"); + fprintf(fp, "tostr_%s(enum %s s)\n", t->name, t->name); + fprintf(fp, "{\n"); + fprintf(fp, " static const char *vals[] = { STRING_%s };\n", t->name); + fprintf(fp, "\n"); + fprintf(fp, " if (isok_%s(s))\n", t->name); + fprintf(fp, " return (vals[(int)s - STROFF_%s]);\n", t->name); + fprintf(fp, " return (\"%s???\");\n", t->name); + fprintf(fp, "}\n\n"); + + if (!ccode) + fprintf(fp, "static inline "); + fprintf(fp, "int\n"); + fprintf(fp, "fromstr_%s(const char *str, enum %s *s)\n", + t->name, t->name); + fprintf(fp, "{\n"); + fprintf(fp, " static const char *vals[] = { STRING_%s };\n", t->name); + fprintf(fp, "\n"); + fprintf(fp, " for (size_t i = 0; i < sizeof(vals)/sizeof(vals[0]); i++) {\n"); + fprintf(fp, " if (vals[i] != NULL && strcmp(vals[i], str) == 0) {\n"); + fprintf(fp, " *s = i + STROFF_%s;\n", t->name); + fprintf(fp, " return (1);\n"); + fprintf(fp, " }\n"); + fprintf(fp, " }\n"); + fprintf(fp, " return (0);\n"); + fprintf(fp, "}\n"); +} + +/** + * Generate helper functions for an enum. This generates code for a c file. + * + * \param fp file to write to + * \param name enum name + */ +static int +gen_enum_funcs_str(FILE *fp, const char *name) +{ + const struct type *t; + + LIST_FOREACH(t, &types, link) + if ((t->is_enum || t->is_bits) && strcmp(t->name, name) == 0) { + gen_enum_funcs(fp, t, 1); + return (0); + } + + return (-1); +} + +/** + * Generate helper functions for all enums. + * + * \param fp file to write to + * \param ccode generate externally visible non-inline functions + */ +static void +gen_all_enum_funcs(FILE *fp, int ccode) +{ + const struct type *t; + + LIST_FOREACH(t, &types, link) + if (t->is_enum || t->is_bits) + gen_enum_funcs(fp, t, ccode); +} + +static void +gen_enums(FILE *fp) +{ + const struct type *t; + + LIST_FOREACH(t, &types, link) + if (t->is_enum || t->is_bits) + gen_enum(fp, t); +} + +/** + * Extract a given enum to the specified file and optionally generate static + * inline helper functions for them. + * + * \param fp file to print on + * \param name name of the enum + * \param gen_funcs generate the functions too + * + * \return 0 if found, -1 otherwise + */ +static int +extract_enum(FILE *fp, const char *name, int gen_funcs) +{ + const struct type *t; + + LIST_FOREACH(t, &types, link) + if ((t->is_enum || t->is_bits) && strcmp(t->name, name) == 0) { + gen_enum(fp, t); + if (gen_funcs) + gen_enum_funcs(fp, t, 0); + return (0); + } + return (-1); +} + +/** + * Extract all enums to the given file and optionally generate static inline + * helper functions for them. + * + * \param fp file to print on + * \param gen_funcs generate the functions too + */ +static void +extract_all_enums(FILE *fp, int gen_funcs) +{ + const struct type *t; + + LIST_FOREACH(t, &types, link) + if (t->is_enum || t->is_bits) { + gen_enum(fp, t); + if (gen_funcs) + gen_enum_funcs(fp, t, 0); + } +} + +/** + * Extract enums and optionally generate some helper functions for them. + * + * \param argc number of arguments + * \param argv arguments (enum names) + * \param gen_funcs_h generate functions into the header file + * \param gen_funcs_c generate a .c file with functions + */ +static void +make_enums(int argc, char *argv[], int gen_funcs_h, int gen_funcs_c) +{ + if (gen_funcs_c) { + if (argc == 0) + gen_all_enum_funcs(stdout, 1); + else { + for (int i = 0; i < argc; i++) + if (gen_enum_funcs_str(stdout, argv[i])) + errx(1, "enum not found: %s", argv[i]); + } + } else { + if (argc == 0) + extract_all_enums(stdout, gen_funcs_h); + else { + for (int i = 0; i < argc; i++) + if (extract_enum(stdout, argv[i], gen_funcs_h)) + errx(1, "enum not found: %s", argv[i]); + } + } +} + +int +main(int argc, char *argv[]) +{ + int do_extract = 0; + int do_tree = 0; + int do_enums = 0; + int gen_funcs_h = 0; + int gen_funcs_c = 0; + int opt; + struct node *root; + char fname[MAXPATHLEN + 1]; + int tok; + FILE *fp; + char *infile = NULL; + + while ((opt = getopt(argc, argv, "dEeFfhI:i:lp:t")) != EOF) + switch (opt) { + + case 'd': + debug = 1; + break; + + case 'E': + do_enums = 1; + break; + + case 'e': + do_extract = 1; + break; + + case 'F': + gen_funcs_c = 1; + break; + + case 'f': + gen_funcs_h = 1; + break; + + case 'h': + fprintf(stderr, "%s", usgtxt); + exit(0); + + case 'I': + path_new(optarg); + break; + + case 'i': + infile = optarg; + break; + + case 'l': + localincs = 1; + break; + + case 'p': + file_prefix = optarg; + if (strlen(file_prefix) + strlen("tree.c") > + MAXPATHLEN) + errx(1, "prefix too long"); + break; + + case 't': + do_tree = 1; + break; + } + + if (do_extract + do_tree + do_enums > 1) + errx(1, "conflicting options -e/-t/-E"); + if (!do_extract && !do_enums && argc != optind) + errx(1, "no arguments allowed"); + if (do_extract && argc == optind) + errx(1, "no objects specified"); + + if ((gen_funcs_h || gen_funcs_c) && !do_enums) + errx(1, "-f and -F require -E"); + if (gen_funcs_h && gen_funcs_c) + errx(1, "-f and -F are mutually exclusive"); + + if (infile == NULL) { + input_new(stdin, NULL, ""); + } else { + if ((fp = fopen(infile, "r")) == NULL) + err(1, "%s", infile); + input_new(fp, NULL, infile); + } + + root = parse_top(gettoken()); + while ((tok = gettoken()) != TOK_EOF) + merge(&root, parse_top(tok)); + + if (root) + check_tree(root); + + if (do_extract) { + while (optind < argc) { + if (gen_extract(stdout, root, argv[optind])) + errx(1, "object not found: %s", argv[optind]); + optind++; + } + return (0); + } + if (do_enums) { + make_enums(argc - optind, argv + optind, + gen_funcs_h, gen_funcs_c); + return (0); + } + if (do_tree) { + gen_tree(root, 0); + return (0); + } + sprintf(fname, "%stree.h", file_prefix); + if ((fp = fopen(fname, "w")) == NULL) + err(1, "%s: ", fname); + gen_header(fp, root, PREFIX_LEN, NULL); + + fprintf(fp, "\n#ifdef SNMPTREE_TYPES\n"); + gen_enums(fp); + fprintf(fp, "\n#endif /* SNMPTREE_TYPES */\n\n"); + + fprintf(fp, "#define %sCTREE_SIZE %u\n", file_prefix, tree_size); + fprintf(fp, "extern const struct snmp_node %sctree[];\n", file_prefix); + + fclose(fp); + + sprintf(fname, "%stree.c", file_prefix); + if ((fp = fopen(fname, "w")) == NULL) + err(1, "%s: ", fname); + gen_table(fp, root); + fclose(fp); + + return (0); +} Property changes on: vendor/bsnmp/1.13/gensnmptree/gensnmptree.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/Makefile.in =================================================================== --- vendor/bsnmp/1.13/lib/Makefile.in (nonexistent) +++ vendor/bsnmp/1.13/lib/Makefile.in (revision 336778) @@ -0,0 +1,34 @@ +# Copyright (c) 2003-2003 +# Fraunhofer Institute for Open Communication Systems (FhG Fokus). +# All rights reserved. +# +# Author: Harti Brandt +# +# $Begemot: bsnmp/trunk/lib/Makefile.in 1487 2008-12-23 19:03:33Z brandt_h $ +# +SRCS= asn1.c snmp.c snmpagent.c snmpclient.c support.c # snmptc.c +INCS= asn1.h snmp.h snmpagent.h snmpclient.h ${builddir}/snmptc.h +MAN3= asn1.3 bsnmplib.3 bsnmpclient.3 bsnmpagent.3 +DEFS= tc.def + +LIB= libbsnmp.la +SHLIB_MAJOR= 6 +SHLIB_MINOR= 0 + +CFLAGS+= -I$(srcdir) + +$(LIB): $(SRCS:.c=.lo) snmptc.h + $(LIBTOOL) --mode=link $(CC) $(LDLAGS) -o $@ $(SRCS:.c=.lo) -rpath $(libdir) -version-info $(SHLIB_MAJOR):$(SHLIB_MINOR) + +snmptc.h : tc.def + ( \ + echo -n "/* autogenerated from tc.def; " ; \ + ls -l -D "%F %T" $(srcdir)/tc.def | awk '{printf("%s %s",$$6,$$7)}' ; \ + echo "*/"; \ + echo "#ifndef snmptc_h_1529923773" ; \ + echo "#define snmptc_h_1529923773" ; \ + ${top_builddir}/gensnmptree/gensnmptree -E -f <${srcdir}/tc.def ; \ + echo "#endif" ; \ + ) >snmptc.h + +CLEANFILES += snmptc.h *.3out Property changes on: vendor/bsnmp/1.13/lib/Makefile.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/asn1.3 =================================================================== --- vendor/bsnmp/1.13/lib/asn1.3 (nonexistent) +++ vendor/bsnmp/1.13/lib/asn1.3 (revision 336778) @@ -0,0 +1,492 @@ +.\" +.\" Copyright (c) 2004-2005 +.\" Hartmut Brandt. +.\" All rights reserved. +.\" Copyright (c) 2001-2003 +.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus). +.\" All rights reserved. +.\" +.\" Author: Harti Brandt +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Begemot: bsnmp/lib/asn1.3,v 1.9 2005/10/04 08:46:49 brandt_h Exp $ +.\" +.Dd October 4, 2005 +.Dt ASN1 3 +.Os +.Sh NAME +.Nm asn_get_header , +.Nm asn_put_header , +.Nm asn_put_temp_header , +.Nm asn_commit_header , +.Nm asn_get_integer_raw , +.Nm asn_get_integer , +.Nm asn_put_integer , +.Nm asn_get_octetstring_raw , +.Nm asn_get_octetstring , +.Nm asn_put_octetstring , +.Nm asn_get_null_raw , +.Nm asn_get_null , +.Nm asn_put_null , +.Nm asn_put_exception , +.Nm asn_get_objid_raw , +.Nm asn_get_objid , +.Nm asn_put_objid , +.Nm asn_get_sequence , +.Nm asn_get_ipaddress_raw , +.Nm asn_get_ipaddress , +.Nm asn_put_ipaddress , +.Nm asn_get_uint32_raw , +.Nm asn_put_uint32 , +.Nm asn_get_counter64_raw , +.Nm asn_put_counter64 , +.Nm asn_get_timeticks , +.Nm asn_put_timeticks , +.Nm asn_skip , +.Nm asn_slice_oid , +.Nm asn_append_oid , +.Nm asn_compare_oid , +.Nm asn_is_suboid , +.Nm asn_oid2str_r , +.Nm asn_oid2str +.Nd "ASN.1 library for SNMP" +.Sh LIBRARY +Begemot SNMP library +.Pq libbsnmp, -lbsnmp +.Sh SYNOPSIS +.In bsnmp/asn1.h +.Ft enum asn_err +.Fn asn_get_header "struct asn_buf *buf" "u_char *type" "asn_len_t *lenp" +.Ft enum asn_err +.Fn asn_put_header "struct asn_buf *buf" "u_char type" "asn_len_t len" +.Ft enum asn_err +.Fn asn_put_temp_header "struct asn_buf *buf" "u_char type" "u_char **ptr" +.Ft enum asn_err +.Fn asn_commit_header "struct asn_buf *buf" "u_char *ptr" +.Ft enum asn_err +.Fn asn_get_integer_raw "struct asn_buf *buf" "asn_len_t len" "int32_t *res" +.Ft enum asn_err +.Fn asn_get_integer "struct asn_buf *buf" "int32_t *res" +.Ft enum asn_err +.Fn asn_put_integer "struct asn_buf *buf" "int32_t arg" +.Ft enum asn_err +.Fn asn_get_octetstring_raw "struct asn_buf *buf" "asn_len_t len" "u_char *out" "u_int *outsize" +.Ft enum asn_err +.Fn asn_get_octetstring "struct asn_buf *buf" "u_char *out" "u_int *outsize" +.Ft enum asn_err +.Fn asn_put_octetstring "struct asn_buf *buf" "const u_char *str" "u_int strsize" +.Ft enum asn_err +.Fn asn_get_null_raw "struct asn_buf *buf" "asn_len_t len" +.Ft enum asn_err +.Fn asn_get_null "struct asn_buf *buf" +.Ft enum asn_err +.Fn asn_put_null "struct asn_buf *buf" +.Ft enum asn_err +.Fn asn_put_exception "struct asn_buf *buf" "u_int type" +.Ft enum asn_err +.Fn asn_get_objid_raw "struct asn_buf *buf" "asn_len_t len" "struct asn_oid *oid" +.Ft enum asn_err +.Fn asn_get_objid "struct asn_buf *buf" "struct asn_oid *oid" +.Ft enum asn_err +.Fn asn_put_objid "struct asn_buf *buf" "const struct asn_oid *oid" +.Ft enum asn_err +.Fn asn_get_sequence "struct asn_buf *buf" "asn_len_t *lenp" +.Ft enum asn_err +.Fn asn_get_ipaddress_raw "struct asn_buf *buf" "asn_len_t len" "u_char *ipa" +.Ft enum asn_err +.Fn asn_get_ipaddress "struct asn_buf *buf" "u_char *ipa" +.Ft enum asn_err +.Fn asn_put_ipaddress "struct asn_buf *buf" "const u_char *ipa" +.Ft enum asn_err +.Fn asn_get_uint32_raw "struct asn_buf *buf" "asn_len_t len" "u_int32_t *res" +.Ft enum asn_err +.Fn asn_put_uint32 "struct asn_buf *buf" "u_char type" "u_int32_t val" +.Ft enum asn_err +.Fn asn_get_counter64_raw "struct asn_buf *buf" "asn_len_t len" "u_int64_t *res" +.Ft enum asn_err +.Fn asn_put_counter64 "struct asn_buf *buf" "u_int64_t val" +.Ft enum asn_err +.Fn asn_get_timeticks "struct asn_buf *buf" "u_int32_t *valp" +.Ft enum asn_err +.Fn asn_put_timeticks "struct asn_buf *buf" "u_int32_t val" +.Ft enum asn_err +.Fn asn_skip "struct asn_buf *buf" "asn_len_t len" +.Ft void +.Fn asn_slice_oid "struct asn_oid *dest" "const struct asn_oid *src" "u_int from" "u_int to" +.Ft void +.Fn asn_append_oid "struct asn_oid *to" "const struct asn_oid *from" +.Ft int +.Fn asn_compare_oid "const struct asn_oid *oid1" "const struct asn_oid *oid2" +.Ft int +.Fn asn_is_suboid "const struct asn_oid *oid1" "const struct asn_oid *oid2" +.Ft char * +.Fn asn_oid2str_r "const struct asn_oid *oid" "char *buf" +.Ft char * +.Fn asn_oid2str "const struct asn_oid *oid" +.Sh DESCRIPTION +The ASN.1 library contains routines to handle ASN.1 encoding for SNMP. +It supports only the restricted form of ASN.1 as required by SNMP. +There are two basic structures used throughout the library: +.Bd -literal -offset indent +/* these restrictions are in the SMI */ +#define ASN_MAXID 0xffffffff +#define ASN_MAXOIDLEN 128 + +/* type of subidentifiers */ +typedef u_int32_t asn_subid_t; + +struct asn_oid { + u_int len; + asn_subid_t subs[ASN_MAXOIDLEN]; +}; +.Ed +.Pp +This structure represents an OID with the restrictions defined in the SNMP +SMI. +.Fa len +holds the current length of the OID and +.Fa subs +holds the elements of the OID. +.Bd -literal -offset indent +struct asn_buf { + union { + u_char *ptr; + const u_char *cptr; + } asn_u; + size_t asn_len; +}; +#define asn_cptr asn_u.cptr +#define asn_ptr asn_u.ptr +.Ed +.Pp +This structure is used to encode and decode ASN.1. +It describes the output +buffer for encoding routines and the input buffer for decoding routines. +For encoding +.Fa asn_len +holds the number of remaining free octets in the buffer. +The first free byte is pointed to by +.Fa asn_ptr . +For decoding +.Fa asn_len +holds the number of remaining bytes to decode. +The next byte to decode is pointed to by +.Fa asn_cptr . +.Pp +Most of the functions return an error code +.Fa "enum asn_error" : +.Bd -literal -offset indent +enum asn_err { + /* conversion was ok */ + ASN_ERR_OK = 0, + /* conversion failed and stopped */ + ASN_ERR_FAILED = 1 | 0x1000, + /* length field bad, value skipped */ + ASN_ERR_BADLEN = 2, + /* out of buffer, stopped */ + ASN_ERR_EOBUF = 3 | 0x1000, + /* length ok, but value is out of range */ + ASN_ERR_RANGE = 4, + /* not the expected tag, stopped */ + ASN_ERR_TAG = 5 | 0x1000, +}; +#define ASN_ERR_STOPPED(E) (((E) & 0x1000) != 0) +.Ed +.Pp +If +.Fn ASN_ERR_STOPPED +returns true, the error was fatal and processing has stopped at the point +of error. +.Pp +The function +.Fn asn_get_header +reads the next header from the input octet stream. +It returns the tag in the variable pointed to by +.Fa type +(note that only single byte tags are supported) and the decoded length field +in the value pointed to by +.Fa lenp +(this is restricted to a unsigned 32-bit value). +All errors in this function are fatal and stop processing. +.Pp +The function +.Fn asn_put_header +writes an ASN.1 header. +.Fa type +is the tag to write and is restricted to one byte tags (i.e., tags +lesser or equal than 0x30). +.Fa len +is the length of the value and is restricted to 16-bit. +.Pp +The functions +.Fn asn_put_temp_header +and +.Fn asn_commit_header +are used to write a header when the length of the value is not known in +advance, for example, for sequences. +.Fn asn_put_temp_header +writes a header with the given tag +.Fa type +and space for the maximum supported length field and sets the pointer pointed +to by +.Fa ptr +to the begin of this length field. +This pointer must then be fed into +.Fn asn_commit_header +directly after writing the value to the buffer. +The function will compute the +length, insert it into the right place and shift the value if the resulting +length field is shorter than the estimated one. +.Pp +The function +.Fn asn_get_integer_raw +is used to decode a signed integer value (32-bit). +It assumes, that the +header of the integer has been decoded already. +.Fa len +is the length obtained from the ASN.1 header and the integer will be returned +in the value pointed to by +.Fa res . +.Pp +The function +.Fn asn_get_integer +decodes a complete 32-bit signed integer including the header. +If the tag is wrong +.Li ASN_ERR_TAG +is returned. +The function +.Fn asn_put_integer +encodes a 32-bit signed integer. +.Pp +The function +.Fn asn_get_octetstring_raw +decodes the value field of an ASN.1 octet string. +The length obtained from the header must be fed into the +.Fa len +argument and +.Fa out +must point to a buffer to receive the octet string. +On entry to the function +.Fa outsize +must point to the size of the buffer. +On exit +.Fa outsize +will point to the number of octets decoded (if no error occurs this will be +equal to +.Fa len ). +The function +.Fn asn_get_octetstring +decodes an octetstring including the header. +.Fa out +must point to a buffer to receive the string, +.Fa outsize +must point to the size of the buffer. +On exit of the function +.Fa outsize +will point to the number of octets decoded. +The function +.Fn asn_put_octetstring +encodes an octetstring (including the header). +.Fa str +points to the string to encode and +.Fa strsize +is the length of the string (the string may contain embedded +.Li NUL Ns s). +.Pp +The function +.Fn asn_get_null_raw +decodes a null value. +.Fa len +is the length obtained from the header and must be 0. +The function +.Fn asn_get_null +decodes a null including the header and the function +.Fn asn_put_null +encodes a null. +.Pp +The function +.Fn asn_put_exception +is used to encode an SNMPv2 exception. +The exception type is +.Fa type . +.Pp +The function +.Fn asn_get_objid_raw +is used to decode an OID value. +.Fa len +must be the value length obtained from the header and +.Fa oid +will receive the decoded OID. +The function +.Fn asn_get_objid +decodes a complete OID (including the header) and the function +.Fn asn_put_objid +encodes a complete OID. +.Pp +The function +.Fn asn_get_sequence +decodes a sequence header. +The length of the sequence value will be stored in the value pointed to by +.Fa lenp . +.Pp +The function +.Fn asn_get_ipaddress_raw +decodes an IP address value. +.Fa len +is the length from the header and must be 4. +.Fa ipa +will receive the decoded IP address and must point to a buffer of at least +four bytes. +The function +.Fn asn_get_ipaddress +decodes a complete IP address (including the header) and +.Fn asn_put_ipaddress +encodes an IP address. +.Pp +The function +.Fn asn_get_uint32_raw +decodes an unsigned 32-bit integer value. +.Fa len +is the length from the header and +.Fa res +will get the decoded value. +The function +.Fn asn_put_uint32 +encodes an unsigned 32-bit integer value and inserts the tag given in +.Fa type +into the header. +.Pp +The function +.Fn asn_get_counter64_raw +decodes an unsigned 64-bit integer value. +.Fa len +must be the value length from the header. +The resulting value is stored into the variable pointed to by +.Fa res . +The function +.Fn asn_put_counter64 +encodes a complete unsigned 64-bit value. +.Pp +The function +.Fn asn_get_timeticks +decodes an ASN.1 object of type +.Li TIMETICKS +and the function +.Fn asn_put_timeticks +encodes such an object. +.Pp +The function +.Fn asn_skip +can be used to skip +.Fa len +bytes in the input buffer. +.Pp +The function +.Fn asn_slice_oid +splits a part out from an OID. +It takes all the subids from the OID pointed to by +.Fa src +starting with the subid at position +.Fa from +(the first subid being subid 0) up to, but not including, subid +.Fa to +and generates a new OID in +.Fa dest . +If +.Fa to +is less or equal to +.Fa from +the resulting OID will have a length of zero. +.Pp +The function +.Fn asn_append_oid +appends the OID +.Fa from +to the OID +.Fa to +given that the resulting OID is not too long. +If the maximum length is exceeded the result is undefined. +.Pp +The function +.Fn asn_compare_oid +compares two oids and returns the values +.Li -1 , +.Li 0 or +.Li +1 +when +.Fa oid1 +is lesser than, equal, or larger than +.Fa oid2 +resp. +.Pp +The function +.Fn asn_is_suboid +returns 1 if +.Fa oid1 +is equal to the leading part of +.Fa oid2 . +It returns 0 otherwise. +.Pp +The function +.Fn asn_oid2str_r +makes a printable string from +.Fa oid . +The buffer pointed to by +.Fa str +must be large enough to hold the result. +The constant +.Li ASN_OIDSTRLEN +is defined to be the length of the maximum string generated by this function +(including the trailing NUL). +The function +.Fn asn_oid2str +makes a printable string from +.Fa oid +into a private buffer that is overwritten by each call. +.Sh DIAGNOSTICS +When an error occurs in any of the function the function pointed to +by the global pointer +.Bd -literal -offset indent +extern void (*asn_error)(const struct asn_buf *, const char *, ...); +.Ed +.Pp +is called with the current buffer (this may be +.Li NULL ) +and a +.Xr printf 3 +style format string. +There is a default error handler in the library that prints a message +starting with +.Sq ASN.1: +followed by the error message and an optional dump of the buffer. +.Sh SEE ALSO +.Xr gensnmptree 1 , +.Xr bsnmpd 1 , +.Xr bsnmpagent 3 , +.Xr bsnmpclient 3 , +.Xr bsnmplib 3 +.Sh STANDARDS +This implementation conforms to the applicable IETF RFCs and ITU-T +recommendations. +.Sh AUTHORS +.An Hartmut Brandt Aq harti@FreeBSD.org Property changes on: vendor/bsnmp/1.13/lib/asn1.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/asn1.c =================================================================== --- vendor/bsnmp/1.13/lib/asn1.c (nonexistent) +++ vendor/bsnmp/1.13/lib/asn1.c (revision 336778) @@ -0,0 +1,1022 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/lib/asn1.c,v 1.31 2005/10/06 07:14:58 brandt_h Exp $ + * + * ASN.1 for SNMP. + */ +#include +#include +#include +#include +#include +#ifdef HAVE_STDINT_H +#include +#elif defined(HAVE_INTTYPES_H) +#include +#endif +#include + +#include "support.h" +#include "asn1.h" + +static void asn_error_func(const struct asn_buf *, const char *, ...); + +void (*asn_error)(const struct asn_buf *, const char *, ...) = asn_error_func; + +/* + * Read the next header. This reads the tag (note, that only single + * byte tags are supported for now) and the length field. The length field + * is restricted to a 32-bit value. + * All errors of this function stop the decoding. + */ +enum asn_err +asn_get_header(struct asn_buf *b, u_char *type, asn_len_t *len) +{ + u_int length; + + if (b->asn_len == 0) { + asn_error(b, "no identifier for header"); + return (ASN_ERR_EOBUF); + } + *type = *b->asn_cptr; + if ((*type & ASN_TYPE_MASK) > 0x30) { + asn_error(b, "types > 0x30 not supported (%u)", + *type & ASN_TYPE_MASK); + return (ASN_ERR_FAILED); + } + b->asn_cptr++; + b->asn_len--; + if (b->asn_len == 0) { + asn_error(b, "no length field"); + return (ASN_ERR_EOBUF); + } + if (*b->asn_cptr & 0x80) { + length = *b->asn_cptr++ & 0x7f; + b->asn_len--; + if (length == 0) { + asn_error(b, "indefinite length not supported"); + return (ASN_ERR_FAILED); + } + if (length > ASN_MAXLENLEN) { + asn_error(b, "long length too long (%u)", length); + return (ASN_ERR_FAILED); + } + if (length > b->asn_len) { + asn_error(b, "long length truncated"); + return (ASN_ERR_EOBUF); + } + *len = 0; + while (length--) { + *len = (*len << 8) | *b->asn_cptr++; + b->asn_len--; + } + } else { + *len = *b->asn_cptr++; + b->asn_len--; + } + return (ASN_ERR_OK); +} + +/* + * Write a length field (restricted to values < 2^32-1) and return the + * number of bytes this field takes. If ptr is NULL, the length is computed + * but nothing is written. If the length would be too large return 0. + */ +static u_int +asn_put_len(u_char *ptr, asn_len_t len) +{ + u_int lenlen, lenlen1; + asn_len_t tmp; + + if (len > ASN_MAXLEN) { + asn_error(NULL, "encoding length too long: (%u)", len); + return (0); + } + + if (len <= 127) { + if (ptr) + *ptr++ = (u_char)len; + return (1); + } else { + lenlen = 0; + /* compute number of bytes for value (is at least 1) */ + for (tmp = len; tmp != 0; tmp >>= 8) + lenlen++; + if (ptr != NULL) { + *ptr++ = (u_char)lenlen | 0x80; + lenlen1 = lenlen; + while (lenlen1-- > 0) { + ptr[lenlen1] = len & 0xff; + len >>= 8; + } + } + return (lenlen + 1); + } +} + +/* + * Write a header (tag and length fields). + * Tags are restricted to one byte tags (value <= 0x30) and the + * lenght field to 16-bit. All errors stop the encoding. + */ +enum asn_err +asn_put_header(struct asn_buf *b, u_char type, asn_len_t len) +{ + u_int lenlen; + + /* tag field */ + if ((type & ASN_TYPE_MASK) > 0x30) { + asn_error(NULL, "types > 0x30 not supported (%u)", + type & ASN_TYPE_MASK); + return (ASN_ERR_FAILED); + } + if (b->asn_len == 0) + return (ASN_ERR_EOBUF); + + *b->asn_ptr++ = type; + b->asn_len--; + + /* length field */ + if ((lenlen = asn_put_len(NULL, len)) == 0) + return (ASN_ERR_FAILED); + if (b->asn_len < lenlen) + return (ASN_ERR_EOBUF); + + (void)asn_put_len(b->asn_ptr, len); + b->asn_ptr += lenlen; + b->asn_len -= lenlen; + return (ASN_ERR_OK); +} + + +/* + * This constructs a temporary sequence header with space for the maximum + * length field (three byte). Set the pointer that ptr points to to the + * start of the encoded header. This is used for a later call to + * asn_commit_header which will fix-up the length field and move the + * value if needed. All errors should stop the encoding. + */ +#define TEMP_LEN (1 + ASN_MAXLENLEN + 1) +enum asn_err +asn_put_temp_header(struct asn_buf *b, u_char type, u_char **ptr) +{ + int ret; + + if (b->asn_len < TEMP_LEN) + return (ASN_ERR_EOBUF); + *ptr = b->asn_ptr; + if ((ret = asn_put_header(b, type, ASN_MAXLEN)) == ASN_ERR_OK) + assert(b->asn_ptr == *ptr + TEMP_LEN); + return (ret); +} +enum asn_err +asn_commit_header(struct asn_buf *b, u_char *ptr, size_t *moved) +{ + asn_len_t len; + u_int lenlen, shift; + + /* compute length of encoded value without header */ + len = b->asn_ptr - (ptr + TEMP_LEN); + + /* insert length. may not fail. */ + lenlen = asn_put_len(ptr + 1, len); + if (lenlen > TEMP_LEN - 1) + return (ASN_ERR_FAILED); + + if (lenlen < TEMP_LEN - 1) { + /* shift value down */ + shift = (TEMP_LEN - 1) - lenlen; + memmove(ptr + 1 + lenlen, ptr + TEMP_LEN, len); + b->asn_ptr -= shift; + b->asn_len += shift; + if (moved != NULL) + *moved = shift; + } + return (ASN_ERR_OK); +} +#undef TEMP_LEN + +/* + * BER integer. This may be used to get a signed 64 bit integer at maximum. + * The maximum length should be checked by the caller. This cannot overflow + * if the caller ensures that len is at maximum 8. + * + * + */ +static enum asn_err +asn_get_real_integer(struct asn_buf *b, asn_len_t len, int64_t *vp) +{ + uint64_t val; + int neg = 0; + enum asn_err err; + + if (b->asn_len < len) { + asn_error(b, "truncated integer"); + return (ASN_ERR_EOBUF); + } + if (len == 0) { + asn_error(b, "zero-length integer"); + *vp = 0; + return (ASN_ERR_BADLEN); + } + err = ASN_ERR_OK; + if (len > 8) + err = ASN_ERR_RANGE; + else if (len > 1 && + ((*b->asn_cptr == 0x00 && (b->asn_cptr[1] & 0x80) == 0) || + (*b->asn_cptr == 0xff && (b->asn_cptr[1] & 0x80) == 0x80))) { + asn_error(b, "non-minimal integer"); + err = ASN_ERR_BADLEN; + } + + if (*b->asn_cptr & 0x80) + neg = 1; + val = 0; + while (len--) { + val <<= 8; + val |= neg ? (u_char)~*b->asn_cptr : *b->asn_cptr; + b->asn_len--; + b->asn_cptr++; + } + if (neg) { + *vp = -(int64_t)val - 1; + } else + *vp = (int64_t)val; + return (err); +} + +/* + * Write a signed integer with the given type. The caller has to ensure + * that the actual value is ok for this type. + */ +static enum asn_err +asn_put_real_integer(struct asn_buf *b, u_char type, int64_t ival) +{ + int i, neg = 0; +# define OCTETS 8 + u_char buf[OCTETS]; + uint64_t val; + enum asn_err ret; + + if (ival < 0) { + /* this may fail if |INT64_MIN| > |INT64_MAX| and + * the value is between * INT64_MIN <= ival < -(INT64_MAX+1) */ + val = (uint64_t)-(ival + 1); + neg = 1; + } else + val = (uint64_t)ival; + + /* split the value into octets */ + for (i = OCTETS - 1; i >= 0; i--) { + buf[i] = val & 0xff; + if (neg) + buf[i] = ~buf[i]; + val >>= 8; + } + /* no leading 9 zeroes or ones */ + for (i = 0; i < OCTETS - 1; i++) + if (!((buf[i] == 0xff && (buf[i + 1] & 0x80) != 0) || + (buf[i] == 0x00 && (buf[i + 1] & 0x80) == 0))) + break; + if ((ret = asn_put_header(b, type, OCTETS - i))) + return (ret); + if (OCTETS - (u_int)i > b->asn_len) + return (ASN_ERR_EOBUF); + + while (i < OCTETS) { + *b->asn_ptr++ = buf[i++]; + b->asn_len--; + } + return (ASN_ERR_OK); +# undef OCTETS +} + + +/* + * The same for unsigned 64-bitters. Here we have the problem, that overflow + * can happen, because the value maybe 9 bytes long. In this case the + * first byte must be 0. + */ +static enum asn_err +asn_get_real_unsigned(struct asn_buf *b, asn_len_t len, uint64_t *vp) +{ + enum asn_err err; + + if (b->asn_len < len) { + asn_error(b, "truncated integer"); + return (ASN_ERR_EOBUF); + } + if (len == 0) { + asn_error(b, "zero-length integer"); + *vp = 0; + return (ASN_ERR_BADLEN); + } + err = ASN_ERR_OK; + *vp = 0; + if ((*b->asn_cptr & 0x80) || (len == 9 && *b->asn_cptr != 0)) { + /* negative integer or too larger */ + *vp = 0xffffffffffffffffULL; + err = ASN_ERR_RANGE; + } else if (len > 1 && + *b->asn_cptr == 0x00 && (b->asn_cptr[1] & 0x80) == 0) { + asn_error(b, "non-minimal unsigned"); + err = ASN_ERR_BADLEN; + } + + while (len--) { + *vp = (*vp << 8) | *b->asn_cptr++; + b->asn_len--; + } + return (err); +} + + +/* + * Values with the msb on need 9 octets. + */ +static int +asn_put_real_unsigned(struct asn_buf *b, u_char type, uint64_t val) +{ + int i; +# define OCTETS 9 + u_char buf[OCTETS]; + enum asn_err ret; + + /* split the value into octets */ + for (i = OCTETS - 1; i >= 0; i--) { + buf[i] = val & 0xff; + val >>= 8; + } + /* no leading 9 zeroes */ + for (i = 0; i < OCTETS - 1; i++) + if (!(buf[i] == 0x00 && (buf[i + 1] & 0x80) == 0)) + break; + if ((ret = asn_put_header(b, type, OCTETS - i))) + return (ret); + if (OCTETS - (u_int)i > b->asn_len) + return (ASN_ERR_EOBUF); + + while (i < OCTETS) { + *b->asn_ptr++ = buf[i++]; + b->asn_len--; + } +#undef OCTETS + return (ASN_ERR_OK); +} + +/* + * The ASN.1 INTEGER type is restricted to 32-bit signed by the SMI. + */ +enum asn_err +asn_get_integer_raw(struct asn_buf *b, asn_len_t len, int32_t *vp) +{ + int64_t val; + enum asn_err ret; + + if ((ret = asn_get_real_integer(b, len, &val)) == ASN_ERR_OK) { + if (len > 4) + ret = ASN_ERR_BADLEN; + else if (val > INT32_MAX || val < INT32_MIN) + /* may not happen */ + ret = ASN_ERR_RANGE; + *vp = (int32_t)val; + } + return (ret); +} + +enum asn_err +asn_get_integer(struct asn_buf *b, int32_t *vp) +{ + asn_len_t len; + u_char type; + enum asn_err err; + + if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK) + return (err); + if (type != ASN_TYPE_INTEGER) { + asn_error(b, "bad type for integer (%u)", type); + return (ASN_ERR_TAG); + } + + return (asn_get_integer_raw(b, len, vp)); +} + +enum asn_err +asn_put_integer(struct asn_buf *b, int32_t val) +{ + return (asn_put_real_integer(b, ASN_TYPE_INTEGER, val)); +} + +/* + * OCTETSTRING + * + * <0x04> + * + * Get an octetstring. noctets must point to the buffer size and on + * return will contain the size of the octetstring, regardless of the + * buffer size. + */ +enum asn_err +asn_get_octetstring_raw(struct asn_buf *b, asn_len_t len, u_char *octets, + u_int *noctets) +{ + enum asn_err err = ASN_ERR_OK; + + if (*noctets < len) { + asn_error(b, "octetstring truncated"); + err = ASN_ERR_RANGE; + } + if (b->asn_len < len) { + asn_error(b, "truncatet octetstring"); + return (ASN_ERR_EOBUF); + } + if (*noctets < len) + memcpy(octets, b->asn_cptr, *noctets); + else + memcpy(octets, b->asn_cptr, len); + *noctets = len; + b->asn_cptr += len; + b->asn_len -= len; + return (err); +} + +enum asn_err +asn_get_octetstring(struct asn_buf *b, u_char *octets, u_int *noctets) +{ + enum asn_err err; + u_char type; + asn_len_t len; + + if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK) + return (err); + if (type != ASN_TYPE_OCTETSTRING) { + asn_error(b, "bad type for octetstring (%u)", type); + return (ASN_ERR_TAG); + } + return (asn_get_octetstring_raw(b, len, octets, noctets)); +} + +enum asn_err +asn_put_octetstring(struct asn_buf *b, const u_char *octets, u_int noctets) +{ + enum asn_err ret; + + if ((ret = asn_put_header(b, ASN_TYPE_OCTETSTRING, noctets)) != ASN_ERR_OK) + return (ret); + if (b->asn_len < noctets) + return (ASN_ERR_EOBUF); + + memcpy(b->asn_ptr, octets, noctets); + b->asn_ptr += noctets; + b->asn_len -= noctets; + return (ASN_ERR_OK); +} + +/* + * NULL + * + * <0x05> <0x00> + */ +enum asn_err +asn_get_null_raw(struct asn_buf *b, asn_len_t len) +{ + if (len != 0) { + if (b->asn_len < len) { + asn_error(b, "truncated NULL"); + return (ASN_ERR_EOBUF); + } + asn_error(b, "bad length for NULL (%u)", len); + b->asn_len -= len; + b->asn_ptr += len; + return (ASN_ERR_BADLEN); + } + return (ASN_ERR_OK); +} + +enum asn_err +asn_get_null(struct asn_buf *b) +{ + u_char type; + asn_len_t len; + enum asn_err err; + + if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK) + return (err); + if (type != ASN_TYPE_NULL) { + asn_error(b, "bad type for NULL (%u)", type); + return (ASN_ERR_TAG); + } + return (asn_get_null_raw(b, len)); +} + +enum asn_err +asn_put_null(struct asn_buf *b) +{ + return (asn_put_header(b, ASN_TYPE_NULL, 0)); +} + +enum asn_err +asn_put_exception(struct asn_buf *b, u_int except) +{ + return (asn_put_header(b, ASN_CLASS_CONTEXT | except, 0)); +} + +/* + * OBJID + * + * <0x06> + */ +enum asn_err +asn_get_objid_raw(struct asn_buf *b, asn_len_t len, struct asn_oid *oid) +{ + asn_subid_t subid; + enum asn_err err; + + if (b->asn_len < len) { + asn_error(b, "truncated OBJID"); + return (ASN_ERR_EOBUF); + } + oid->len = 0; + if (len == 0) { + asn_error(b, "short OBJID"); + oid->subs[oid->len++] = 0; + oid->subs[oid->len++] = 0; + return (ASN_ERR_BADLEN); + } + err = ASN_ERR_OK; + while (len != 0) { + if (oid->len == ASN_MAXOIDLEN) { + asn_error(b, "OID too long (%u)", oid->len); + b->asn_cptr += len; + b->asn_len -= len; + return (ASN_ERR_BADLEN); + } + subid = 0; + do { + if (len == 0) { + asn_error(b, "unterminated subid"); + return (ASN_ERR_EOBUF); + } + if (subid > (ASN_MAXID >> 7)) { + asn_error(b, "OBID subid too larger"); + err = ASN_ERR_RANGE; + } + subid = (subid << 7) | (*b->asn_cptr & 0x7f); + len--; + b->asn_len--; + } while (*b->asn_cptr++ & 0x80); + if (oid->len == 0) { + if (subid < 80) { + oid->subs[oid->len++] = subid / 40; + oid->subs[oid->len++] = subid % 40; + } else { + oid->subs[oid->len++] = 2; + oid->subs[oid->len++] = subid - 80; + } + } else { + oid->subs[oid->len++] = subid; + } + } + return (err); + +} + +enum asn_err +asn_get_objid(struct asn_buf *b, struct asn_oid *oid) +{ + u_char type; + asn_len_t len; + enum asn_err err; + + if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK) + return (err); + if (type != ASN_TYPE_OBJID) { + asn_error(b, "bad type for OBJID (%u)", type); + return (ASN_ERR_TAG); + } + return (asn_get_objid_raw(b, len, oid)); +} + +enum asn_err +asn_put_objid(struct asn_buf *b, const struct asn_oid *oid) +{ + asn_subid_t first, sub; + enum asn_err err, err1; + u_int i, oidlen; + asn_len_t len; + + err = ASN_ERR_OK; + if (oid->len == 0) { + /* illegal */ + asn_error(NULL, "short oid"); + err = ASN_ERR_RANGE; + first = 0; + oidlen = 2; + } else if (oid->len == 1) { + /* illegal */ + asn_error(b, "short oid"); + if (oid->subs[0] > 2) + asn_error(NULL, "oid[0] too large (%u)", oid->subs[0]); + err = ASN_ERR_RANGE; + first = oid->subs[0] * 40; + oidlen = 2; + } else { + if (oid->len > ASN_MAXOIDLEN) { + asn_error(NULL, "oid too long %u", oid->len); + err = ASN_ERR_RANGE; + } + if (oid->subs[0] > 2 || + (oid->subs[0] < 2 && oid->subs[1] >= 40)) { + asn_error(NULL, "oid out of range (%u,%u)", + oid->subs[0], oid->subs[1]); + err = ASN_ERR_RANGE; + } + first = 40 * oid->subs[0] + oid->subs[1]; + oidlen = oid->len; + } + len = 0; + for (i = 1; i < oidlen; i++) { + sub = (i == 1) ? first : oid->subs[i]; + if (sub > ASN_MAXID) { + asn_error(NULL, "oid subid too large"); + err = ASN_ERR_RANGE; + } + len += (sub <= 0x7f) ? 1 + : (sub <= 0x3fff) ? 2 + : (sub <= 0x1fffff) ? 3 + : (sub <= 0xfffffff) ? 4 + : 5; + } + if ((err1 = asn_put_header(b, ASN_TYPE_OBJID, len)) != ASN_ERR_OK) + return (err1); + if (b->asn_len < len) + return (ASN_ERR_EOBUF); + + for (i = 1; i < oidlen; i++) { + sub = (i == 1) ? first : oid->subs[i]; + if (sub <= 0x7f) { + *b->asn_ptr++ = sub; + b->asn_len--; + } else if (sub <= 0x3fff) { + *b->asn_ptr++ = (sub >> 7) | 0x80; + *b->asn_ptr++ = sub & 0x7f; + b->asn_len -= 2; + } else if (sub <= 0x1fffff) { + *b->asn_ptr++ = (sub >> 14) | 0x80; + *b->asn_ptr++ = ((sub >> 7) & 0x7f) | 0x80; + *b->asn_ptr++ = sub & 0x7f; + b->asn_len -= 3; + } else if (sub <= 0xfffffff) { + *b->asn_ptr++ = (sub >> 21) | 0x80; + *b->asn_ptr++ = ((sub >> 14) & 0x7f) | 0x80; + *b->asn_ptr++ = ((sub >> 7) & 0x7f) | 0x80; + *b->asn_ptr++ = sub & 0x7f; + b->asn_len -= 4; + } else { + *b->asn_ptr++ = (sub >> 28) | 0x80; + *b->asn_ptr++ = ((sub >> 21) & 0x7f) | 0x80; + *b->asn_ptr++ = ((sub >> 14) & 0x7f) | 0x80; + *b->asn_ptr++ = ((sub >> 7) & 0x7f) | 0x80; + *b->asn_ptr++ = sub & 0x7f; + b->asn_len -= 5; + } + } + return (err); +} +/* + * SEQUENCE header + * + * <0x10|0x20> + */ +enum asn_err +asn_get_sequence(struct asn_buf *b, asn_len_t *len) +{ + u_char type; + enum asn_err err; + + if ((err = asn_get_header(b, &type, len)) != ASN_ERR_OK) + return (err); + if (type != (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED)) { + asn_error(b, "bad sequence type %u", type); + return (ASN_ERR_TAG); + } + if (*len > b->asn_len) { + asn_error(b, "truncated sequence"); + return (ASN_ERR_EOBUF); + } + return (ASN_ERR_OK); +} + +/* + * Application types + * + * 0x40 4 MSB 2MSB 2LSB LSB + */ +enum asn_err +asn_get_ipaddress_raw(struct asn_buf *b, asn_len_t len, u_char *addr) +{ + u_int i; + + if (b->asn_len < len) { + asn_error(b, "truncated ip-address"); + return (ASN_ERR_EOBUF); + } + if (len < 4) { + asn_error(b, "short length for ip-Address %u", len); + for (i = 0; i < len; i++) + *addr++ = *b->asn_cptr++; + while (i++ < len) + *addr++ = 0; + b->asn_len -= len; + return (ASN_ERR_BADLEN); + } + for (i = 0; i < 4; i++) + *addr++ = *b->asn_cptr++; + b->asn_cptr += len - 4; + b->asn_len -= len; + return (ASN_ERR_OK); +} + +enum asn_err +asn_get_ipaddress(struct asn_buf *b, u_char *addr) +{ + u_char type; + asn_len_t len; + enum asn_err err; + + if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK) + return (err); + if (type != (ASN_CLASS_APPLICATION|ASN_APP_IPADDRESS)) { + asn_error(b, "bad type for ip-address %u", type); + return (ASN_ERR_TAG); + } + return (asn_get_ipaddress_raw(b, len, addr)); +} + +enum asn_err +asn_put_ipaddress(struct asn_buf *b, const u_char *addr) +{ + enum asn_err err; + + if ((err = asn_put_header(b, ASN_CLASS_APPLICATION|ASN_APP_IPADDRESS, + 4)) != ASN_ERR_OK) + return (err); + if (b->asn_len < 4) + return (ASN_ERR_EOBUF); + + memcpy(b->asn_ptr, addr, 4); + b->asn_ptr += 4; + b->asn_len -= 4; + return (ASN_ERR_OK); +} + + +/* + * UNSIGNED32 + * + * 0x42|0x41 ... + */ +enum asn_err +asn_get_uint32_raw(struct asn_buf *b, asn_len_t len, uint32_t *vp) +{ + uint64_t v; + enum asn_err err; + + if ((err = asn_get_real_unsigned(b, len, &v)) == ASN_ERR_OK) { + if (len > 5) { + asn_error(b, "uint32 too long %u", len); + err = ASN_ERR_BADLEN; + } else if (v > UINT32_MAX) { + asn_error(b, "uint32 too large %llu", v); + err = ASN_ERR_RANGE; + } + *vp = (uint32_t)v; + } + return (err); +} + +enum asn_err +asn_put_uint32(struct asn_buf *b, u_char type, uint32_t val) +{ + uint64_t v = val; + + return (asn_put_real_unsigned(b, ASN_CLASS_APPLICATION|type, v)); +} + +/* + * COUNTER64 + * 0x46 ... + */ +enum asn_err +asn_get_counter64_raw(struct asn_buf *b, asn_len_t len, uint64_t *vp) +{ + return (asn_get_real_unsigned(b, len, vp)); +} + +enum asn_err +asn_put_counter64(struct asn_buf *b, uint64_t val) +{ + return (asn_put_real_unsigned(b, + ASN_CLASS_APPLICATION | ASN_APP_COUNTER64, val)); +} + +/* + * TimeTicks + * 0x43 ... + */ +enum asn_err +asn_get_timeticks(struct asn_buf *b, uint32_t *vp) +{ + asn_len_t len; + u_char type; + enum asn_err err; + + if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK) + return (err); + if (type != (ASN_CLASS_APPLICATION|ASN_APP_TIMETICKS)) { + asn_error(b, "bad type for timeticks %u", type); + return (ASN_ERR_TAG); + } + return (asn_get_uint32_raw(b, len, vp)); +} + +enum asn_err +asn_put_timeticks(struct asn_buf *b, uint32_t val) +{ + uint64_t v = val; + + return (asn_put_real_unsigned(b, + ASN_CLASS_APPLICATION | ASN_APP_TIMETICKS, v)); +} + +/* + * Construct a new OID by taking a range of sub ids of the original oid. + */ +void +asn_slice_oid(struct asn_oid *dest, const struct asn_oid *src, + u_int from, u_int to) +{ + if (from >= to) { + dest->len = 0; + return; + } + dest->len = to - from; + memcpy(dest->subs, &src->subs[from], dest->len * sizeof(dest->subs[0])); +} + +/* + * Append from to to + */ +void +asn_append_oid(struct asn_oid *to, const struct asn_oid *from) +{ + memcpy(&to->subs[to->len], &from->subs[0], + from->len * sizeof(from->subs[0])); + to->len += from->len; +} + +/* + * Skip a value + */ +enum asn_err +asn_skip(struct asn_buf *b, asn_len_t len) +{ + if (b->asn_len < len) + return (ASN_ERR_EOBUF); + b->asn_cptr += len; + b->asn_len -= len; + return (ASN_ERR_OK); +} + +/* + * Add a padding + */ +enum asn_err +asn_pad(struct asn_buf *b, asn_len_t len) +{ + if (b->asn_len < len) + return (ASN_ERR_EOBUF); + b->asn_ptr += len; + b->asn_len -= len; + + return (ASN_ERR_OK); +} + +/* + * Compare two OIDs. + * + * o1 < o2 : -1 + * o1 > o2 : +1 + * o1 = o2 : 0 + */ +int +asn_compare_oid(const struct asn_oid *o1, const struct asn_oid *o2) +{ + u_long i; + + for (i = 0; i < o1->len && i < o2->len; i++) { + if (o1->subs[i] < o2->subs[i]) + return (-1); + if (o1->subs[i] > o2->subs[i]) + return (+1); + } + if (o1->len < o2->len) + return (-1); + if (o1->len > o2->len) + return (+1); + return (0); +} + +/* + * Check whether an OID is a sub-string of another OID. + */ +int +asn_is_suboid(const struct asn_oid *o1, const struct asn_oid *o2) +{ + u_long i; + + for (i = 0; i < o1->len; i++) + if (i >= o2->len || o1->subs[i] != o2->subs[i]) + return (0); + return (1); +} + +/* + * Put a string representation of an oid into a user buffer. This buffer + * is assumed to be at least ASN_OIDSTRLEN characters long. + * + * sprintf is assumed not to fail here. + */ +char * +asn_oid2str_r(const struct asn_oid *oid, char *buf) +{ + u_int len, i; + char *ptr; + + if ((len = oid->len) > ASN_MAXOIDLEN) + len = ASN_MAXOIDLEN; + buf[0] = '\0'; + for (i = 0, ptr = buf; i < len; i++) { + if (i > 0) + *ptr++ = '.'; + ptr += sprintf(ptr, "%u", oid->subs[i]); + } + return (buf); +} + +/* + * Make a string from an OID in a private buffer. + */ +char * +asn_oid2str(const struct asn_oid *oid) +{ + static char str[ASN_OIDSTRLEN]; + + return (asn_oid2str_r(oid, str)); +} + + +static void +asn_error_func(const struct asn_buf *b, const char *err, ...) +{ + va_list ap; + u_long i; + + fprintf(stderr, "ASN.1: "); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + + if (b != NULL) { + fprintf(stderr, " at"); + for (i = 0; b->asn_len > i; i++) + fprintf(stderr, " %02x", b->asn_cptr[i]); + } + fprintf(stderr, "\n"); +} Property changes on: vendor/bsnmp/1.13/lib/asn1.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/asn1.h =================================================================== --- vendor/bsnmp/1.13/lib/asn1.h (nonexistent) +++ vendor/bsnmp/1.13/lib/asn1.h (revision 336778) @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/lib/asn1.h,v 1.20 2005/10/05 16:43:11 brandt_h Exp $ + * + * ASN.1 for SNMP + */ +#ifndef asn1_h_ +#define asn1_h_ + +#include + +struct asn_buf { + union { + u_char *ptr; + const u_char *cptr; + } asn_u; + size_t asn_len; +}; +#define asn_cptr asn_u.cptr +#define asn_ptr asn_u.ptr + +/* these restrictions are in the SMI */ +#define ASN_MAXID 0xffffffff +#define ASN_MAXOIDLEN 128 + +/* the string needed for this (with trailing zero) */ +#define ASN_OIDSTRLEN (ASN_MAXOIDLEN * (10 + 1) - 1 + 1) + +/* type of subidentifiers */ +typedef uint32_t asn_subid_t; + +struct asn_oid { + u_int len; + asn_subid_t subs[ASN_MAXOIDLEN]; +}; + +enum asn_err { + /* conversion was ok */ + ASN_ERR_OK = 0, + /* conversion failed and stopped */ + ASN_ERR_FAILED = 1 | 0x1000, + /* length field bad, value skipped */ + ASN_ERR_BADLEN = 2, + /* out of buffer, stopped */ + ASN_ERR_EOBUF = 3 | 0x1000, + /* length ok, but value is out of range */ + ASN_ERR_RANGE = 4, + /* not the expected tag, stopped */ + ASN_ERR_TAG = 5 | 0x1000, +}; +#define ASN_ERR_STOPPED(E) (((E) & 0x1000) != 0) + +/* type for the length field of encoded values. The length is restricted + * to 65535, but using uint16_t would give conversion warnings on gcc */ +typedef uint32_t asn_len_t; /* could be also uint16_t */ + +/* maximal length of a long length field without the length of the length */ +#define ASN_MAXLEN 65535 +#define ASN_MAXLENLEN 2 /* number of bytes in a length */ + +/* maximum size of an octet string as per SMIv2 */ +#define ASN_MAXOCTETSTRING 65535 + +extern void (*asn_error)(const struct asn_buf *, const char *, ...); + +enum asn_err asn_get_header(struct asn_buf *, u_char *, asn_len_t *); +enum asn_err asn_put_header(struct asn_buf *, u_char, asn_len_t); + +enum asn_err asn_put_temp_header(struct asn_buf *, u_char, u_char **); +enum asn_err asn_commit_header(struct asn_buf *, u_char *, size_t *); + +enum asn_err asn_get_integer_raw(struct asn_buf *, asn_len_t, int32_t *); +enum asn_err asn_get_integer(struct asn_buf *, int32_t *); +enum asn_err asn_put_integer(struct asn_buf *, int32_t); + +enum asn_err asn_get_octetstring_raw(struct asn_buf *, asn_len_t, u_char *, u_int *); +enum asn_err asn_get_octetstring(struct asn_buf *, u_char *, u_int *); +enum asn_err asn_put_octetstring(struct asn_buf *, const u_char *, u_int); + +enum asn_err asn_get_null_raw(struct asn_buf *b, asn_len_t); +enum asn_err asn_get_null(struct asn_buf *); +enum asn_err asn_put_null(struct asn_buf *); + +enum asn_err asn_put_exception(struct asn_buf *, u_int); + +enum asn_err asn_get_objid_raw(struct asn_buf *, asn_len_t, struct asn_oid *); +enum asn_err asn_get_objid(struct asn_buf *, struct asn_oid *); +enum asn_err asn_put_objid(struct asn_buf *, const struct asn_oid *); + +enum asn_err asn_get_sequence(struct asn_buf *, asn_len_t *); + +enum asn_err asn_get_ipaddress_raw(struct asn_buf *, asn_len_t, u_char *); +enum asn_err asn_get_ipaddress(struct asn_buf *, u_char *); +enum asn_err asn_put_ipaddress(struct asn_buf *, const u_char *); + +enum asn_err asn_get_uint32_raw(struct asn_buf *, asn_len_t, uint32_t *); +enum asn_err asn_put_uint32(struct asn_buf *, u_char, uint32_t); + +enum asn_err asn_get_counter64_raw(struct asn_buf *, asn_len_t, uint64_t *); +enum asn_err asn_put_counter64(struct asn_buf *, uint64_t); + +enum asn_err asn_get_timeticks(struct asn_buf *, uint32_t *); +enum asn_err asn_put_timeticks(struct asn_buf *, uint32_t); + +enum asn_err asn_skip(struct asn_buf *, asn_len_t); +enum asn_err asn_pad(struct asn_buf *, asn_len_t); + +/* + * Utility functions for OIDs + */ +/* get a sub-OID from the middle of another OID */ +void asn_slice_oid(struct asn_oid *, const struct asn_oid *, u_int, u_int); + +/* append an OID to another one */ +void asn_append_oid(struct asn_oid *, const struct asn_oid *); + +/* compare two OIDs */ +int asn_compare_oid(const struct asn_oid *, const struct asn_oid *); + +/* check whether the first is a suboid of the second one */ +int asn_is_suboid(const struct asn_oid *, const struct asn_oid *); + +/* format an OID into a user buffer of size ASN_OIDSTRLEN */ +char *asn_oid2str_r(const struct asn_oid *, char *); + +/* format an OID into a private static buffer */ +char *asn_oid2str(const struct asn_oid *); + +enum { + ASN_TYPE_BOOLEAN = 0x01, + ASN_TYPE_INTEGER = 0x02, + ASN_TYPE_BITSTRING = 0x03, + ASN_TYPE_OCTETSTRING = 0x04, + ASN_TYPE_NULL = 0x05, + ASN_TYPE_OBJID = 0x06, + ASN_TYPE_SEQUENCE = 0x10, + + ASN_TYPE_CONSTRUCTED = 0x20, + ASN_CLASS_UNIVERSAL = 0x00, + ASN_CLASS_APPLICATION = 0x40, + ASN_CLASS_CONTEXT = 0x80, + ASN_CLASS_PRIVATE = 0xc0, + ASN_TYPE_MASK = 0x1f, + + ASN_APP_IPADDRESS = 0x00, + ASN_APP_COUNTER = 0x01, + ASN_APP_GAUGE = 0x02, + ASN_APP_TIMETICKS = 0x03, + ASN_APP_OPAQUE = 0x04, /* not implemented */ + ASN_APP_COUNTER64 = 0x06, + + ASN_EXCEPT_NOSUCHOBJECT = 0x00, + ASN_EXCEPT_NOSUCHINSTANCE = 0x01, + ASN_EXCEPT_ENDOFMIBVIEW = 0x02, +}; + +#endif Property changes on: vendor/bsnmp/1.13/lib/asn1.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/bsnmpagent.3 =================================================================== --- vendor/bsnmp/1.13/lib/bsnmpagent.3 (nonexistent) +++ vendor/bsnmp/1.13/lib/bsnmpagent.3 (revision 336778) @@ -0,0 +1,444 @@ +.\" +.\" Copyright (c) 2004-2005 +.\" Hartmut Brandt. +.\" All rights reserved. +.\" Copyright (c) 2001-2003 +.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus). +.\" All rights reserved. +.\" +.\" Author: Harti Brandt +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Begemot: bsnmp/lib/bsnmpagent.3,v 1.10 2005/10/04 08:46:49 brandt_h Exp $ +.\" +.Dd October 4, 2005 +.Dt BSNMPAGENT 3 +.Os +.Sh NAME +.Nm bsnmpagent , +.Nm snmp_depop_t , +.Nm snmp_op_t , +.Nm tree , +.Nm tree_size , +.Nm snmp_trace , +.Nm snmp_debug , +.Nm snmp_get , +.Nm snmp_getnext , +.Nm snmp_getbulk , +.Nm snmp_set , +.Nm snmp_make_errresp , +.Nm snmp_dep_lookup , +.Nm snmp_init_context , +.Nm snmp_dep_commit , +.Nm snmp_dep_rollback , +.Nm snmp_dep_finish +.Nd "SNMP agent library" +.Sh LIBRARY +Begemot SNMP library +.Pq libbsnmp, -lbsnmp +.Sh SYNOPSIS +.In asn1.h +.In snmp.h +.In snmpagent.h +.Ft typedef int +.Fn (*snmp_depop_t) "struct snmp_context *ctx" "struct snmp_dependency *dep" "enum snmp_depop op" +.Ft typedef int +.Fn (*snmp_op_t) "struct snmp_context *ctx" "struct snmp_value *val" "u_int len" "u_int idx" "enum snmp_op op" +.Vt extern struct snmp_node *tree ; +.Vt extern u_int tree_size ; +.Vt extern u_int snmp_trace ; +.Vt extern void (*snmp_debug)(const char *fmt, ...) ; +.Ft enum snmp_ret +.Fn snmp_get "struct snmp_pdu *pdu" "struct asn_buf *resp_b" "struct snmp_pdu *resp" "void *data" +.Ft enum snmp_ret +.Fn snmp_getnext "struct snmp_pdu *pdu" "struct asn_buf *resp_b" "struct snmp_pdu *resp" "void *data" +.Ft enum snmp_ret +.Fn snmp_getbulk "struct snmp_pdu *pdu" "struct asn_buf *resp_b" "struct snmp_pdu *resp" "void *data" +.Ft enum snmp_ret +.Fn snmp_set "struct snmp_pdu *pdu" "struct asn_buf *resp_b" "struct snmp_pdu *resp" "void *data" +.Ft enum snmp_ret +.Fn snmp_make_errresp "const struct snmp_pdu *pdu" "struct asn_buf *req_b" "struct asn_buf *resp_b" +.Ft struct snmp_dependency * +.Fn snmp_dep_lookup "struct snmp_context *ctx" "const struct asn_oid *base" "const struct asn_oid *idx" "size_t alloc" "snmp_depop_t func" +.Ft struct snmp_context * +.Fn snmp_init_context "void" +.Ft int +.Fn snmp_dep_commit "struct snmp_context *ctx" +.Ft int +.Fn snmp_dep_rollback "struct snmp_context *ctx" +.Ft void +.Fn snmp_dep_finish "struct snmp_context *ctx" +.Sh DESCRIPTION +The SNMP library contains routines to easily build SNMP agent applications +that use SNMP versions 1 or 2. +Note, however, that it may be even easier to build an +.Xr bsnmpd 1 +loadable module, that handles the new MIB (see +.Xr snmpmod 3 ) . +.Pp +Most of the agent routines operate on a global array that the describes the +complete MIB served by the agent. +This array is held in the two variables: +.Bd -literal -offset indent +extern struct snmp_node *tree; +extern u_int tree_size; +.Ed +.Pp +The elements of the array are of type +.Vt struct snmp_node : +.Bd -literal -offset indent +typedef int (*snmp_op_t)(struct snmp_context *, struct snmp_value *, + u_int, u_int, enum snmp_op); + +struct snmp_node { + struct asn_oid oid; + const char *name; /* name of the leaf */ + enum snmp_node_type type; /* type of this node */ + enum snmp_syntax syntax; + snmp_op_t op; + u_int flags; + u_int32_t index; /* index data */ + void *data; /* application data */ + void *tree_data; /* application data */ +}; +.Ed +.Pp +The fields of this structure are described below. +.Bl -tag -width "syntax" +.It Va oid +Base OID of the scalar or table column. +.It Va name +Name of this variable. +.It Va type +Type of this variable. +One of: +.Bd -literal -offset indent +enum snmp_node_type { + SNMP_NODE_LEAF = 1, + SNMP_NODE_COLUMN +}; +.Ed +.It Va syntax +The SNMP syntax of this variable. +.It Va op +The user supplied handler for this variable. +The handler is called with the following arguments: +.Bl -tag -width "ctx" +.It Fa ctx +A pointer to the context (see below). +.Li NULL . +.It Fa val +The value to be set or retrieved. +For GETNEXT and GETBULK operations the oid in +this value is the current OID. +The function (called in this case only for +table rows) must find the lexically next existing OID within the same column and +set the oid and value subfields accordingly. +If the table column is exhausted the +function must return +.Li SNMP_ERR_NOSUCHNAME . +For all other operations the oid in +.Fa val +is the oid to fetch or set. +.It Fa len +The length of the base oid without index. +.It Fa idx +For table columns this is the index expression from the node (see below). +.It Fa op +This is the operation to execute, one of: +.Bd -literal -offset indent +enum snmp_op { + SNMP_OP_GET = 1, + SNMP_OP_GETNEXT, + SNMP_OP_SET, + SNMP_OP_COMMIT, + SNMP_OP_ROLLBACK, +}; +.Ed +.El +.Pp +The user handler must return an appropriate SNMP v2 error code. +If the original +PDU was a version 1 PDU, the error code is mapped automatically. +.It Va flags +Currently only the flag +.Li SNMP_NODE_CANSET is defined and set for nodes, that can be written or +created. +.It Va index +This word describes the index for table columns. +Each part of the index takes 4 bits starting at bit 4. +Bits 0 to 3 hold the number of index parts. +This arrangement allows for tables with up to seven indexes. +Each bit group contains the syntax for the index part. +There are a number of macros to help in parsing this field: +.Bd -literal -offset indent +#define SNMP_INDEXES_MAX 7 +#define SNMP_INDEX_SHIFT 4 +#define SNMP_INDEX_MASK 0xf +#define SNMP_INDEX_COUNT(V) ((V) & SNMP_INDEX_MASK) +#define SNMP_INDEX(V,I) \e + (((V) >> (((I) + 1) * SNMP_INDEX_SHIFT)) & \e + SNMP_INDEX_MASK) +.Ed +.It Va data +This field may contain arbitrary data and is not used by the library. +.El +.Pp +The easiest way to construct the node table is +.Xr gensnmptree 1 . +Note, that one must be careful when changing the tree while executing a SET +operation. +Consult the sources for +.Xr bsnmpd 1 . +.Pp +The global variable +.Va snmp_trace +together with the function pointed to by +.Va snmp_debug +help in debugging the library and the agent. +.Va snmp_trace is a bit mask with the following bits: +.Bd -literal -offset indent +enum { + SNMP_TRACE_GET, + SNMP_TRACE_GETNEXT, + SNMP_TRACE_SET, + SNMP_TRACE_DEPEND, + SNMP_TRACE_FIND, +}; +.Ed +.Pp +Setting a bit to true causes the library to call +.Fn snmp_debug +in strategic places with a debug string. +The library contains a default +implementation for the debug function that prints a message to standard error. +.Pp +Many of the functions use a so called context: +.Bd -literal -offset indent +struct snmp_context { + u_int var_index; + struct snmp_scratch *scratch; + struct snmp_dependency *dep; + void *data; /* user data */ + enum snmp_ret code; /* return code */ +}; + +struct snmp_scratch { + void *ptr1; + void *ptr2; + uint32_t int1; + uint32_t int2; +}; +.Ed +.Pp +The fields are used as follows: +.Bl -tag -width ".It Va var_index" +.It Va va_index +For the node operation callback this is the +index of the variable binding that should be returned if an error occurs. +Set by the library. +In all other functions this is undefined. +.It Va scratch +For the node operation callback this is a pointer to a per variable binding +scratch area that can be used to implement the commit and rollback. +Set by the library. +.It Va dep +In the dependency callback function (see below) this is a pointer to the +current dependency. +Set by the library. +.It Va data +This is the +.Fa data +argument from the call to the library and is not used by the library. +.El +.Pp +The next three functions execute different kinds of GET requests. +The function +.Fn snmp_get +executes an SNMP GET operation, the function +.Fn snmp_getnext +executes an SNMP GETNEXT operation and the function +.Fn snmp_getbulk +executes an SNMP GETBULK operation. +For all three functions the response PDU is constructed and encoded +on the fly. +If everything is ok, the response PDU is returned in +.Fa resp +and +.Fa resp_b . +The caller must call +.Fn snmp_pdu_free +to free the response PDU in this case. +One of the following values may be returned: +.Bl -tag -width ".It Li SNMP_RET_ERR" +.It Li SNMP_RET_OK +Operation successful, response PDU may be sent. +.It Li SNMP_RET_IGN +Operation failed, no response PDU constructed. +Request is ignored. +.It Li SNMP_RET_ERR +Error in operation. +The error code and index have been set in +.Fa pdu . +No response PDU has been constructed. +The caller may construct an error response PDU via +.Fn snmp_make_errresp . +.El +.Pp +The function +.Fn snmp_set +executes an SNMP SET operation. +The arguments are the same as for the previous +three functions. +The operation of this functions is, however, much more complex. +.Pp +The SET operation occurs in several stages: +.Bl -enum -offset indent +.It +For each binding search the corresponding nodes, check that the +variable is writeable and the syntax is ok. +The writeable check can be done only for scalars. +For columns it must be done in the node's operation callback function. +.It +For each binding call the node's operation callback with function SNMP_OP_SET. +The callback may create dependencies or finalizers (see below). +For simple +scalars the scratch area may be enough to handle commit and rollback, for +interdependent table columns dependencies may be necessary. +.It +If the previous step fails at any point, the node's operation callback +functions are called for all bindings for which SNMP_OP_SET was executed +with SNMP_OP_ROLLBACK, in the opposite order. +This allows all variables to undo the effect of the SET operation. +After this all the dependencies are freed +and the finalizers are executed with a fail flag of 1. +Then the function +returns to the caller with an appropriate error indication. +.It +If the SET step was successful for all bindings, the dependency callbacks +are executed in the order in which the dependencies were created with an +operation of SNMP_DEPOP_COMMIT. +If any of the dependencies fails, all the +committed dependencies are called again in the opposite order +with SNMP_DEPOP_ROLLBACK. +Than for all bindings from the last to the first +the node's operation callback is called with SNMP_OP_ROLLBACK to undo +the effect of SNMP_OP_SET. +At the end the dependencies are freed and the finalizers are called with +a fail flag of 1 and the function returns to the caller with an appropriate +error indication. +.It +If the dependency commits were successful, for each binding the node's +operation callback is called with SNMP_OP_COMMIT. +Any error returned from +the callbacks is ignored (an error message is generated via +.Fn snmp_error ). +.It +Now the dependencies are freed and the finalizers are called +with a fail flag of 0. +For each dependency just before freeing it +its callback is called with +.Li SNMP_DEPOP_FINISH. +Then the function returns +.Li SNMP_ERR_OK . +.El +.Pp +There are to mechanisms to help in complex SET operations: dependencies and +finalizers. +A dependency is used if several bindings depend on each other. +A typical example is the creation of a conceptual row, which requires +the setting of several columns to succeed. +A dependency is identified by +two OIDs. +In the table case, the first oid is typically the table's base OID +and the second one the index. +Both of these can easily be generated from the +variables OID with +.Fn asn_slice_oid . +The function +.Fn snmp_dep_lookup +tries to find a dependency based on these two OIDs and, if it cannot find one +creates a new one. +This means for the table example, that the function +returns the same dependency for each of the columns of the same table row. +This allows during the SNMP_OP_SET processing to collect all information +about the row into the dependency. +The arguments to +.Fn snmp_dep_lookup +are: the two OIDs to identify the dependency (they are copied into newly +created dependencies), the size of the structure to allocate and +the dependency callback. +.Pp +When all SNMP_OP_SET operations have succeeded the dependencies are executed. +At this stage the dependency callback has all information about the given +table row that was available in this SET PDU and can operate accordingly. +.Pp +It is guaranteed that each dependency callback is executed at minimum once +- with an operation of +.Li SNMP_OP_ROLLBACK . +This ensures that all dynamically allocated resources in a callback can be +freed correctly. +.Pp +The function +.Fn snmp_make_errresp +makes an error response if an operation has failed. +It takes the original request PDU (it will look only on the error code and +index fields), the buffer containing the original PDU and a buffer for the +error PDU. +It copies the bindings field from the original PDUs buffer directly to +the response PDU and thus does not depend on the decodability of this field. +It may return the same values as the operation functions. +.Pp +The next four functions allow some parts of the SET operation to be executed. +This is only used in +.Xr bsnmpd 1 +to implement the configuration as a single transaction. +The function +.Fn snmp_init_context +creates and initializes a context. +The function +.Fn snmp_dep_commit +executes SNMP_DEPOP_COMMIT for all dependencies in the context stopping at +the first error. +The function +.Fn snmp_dep_rollback +executes SNMP_DEPOP_ROLLBACK starting at the previous of the current +dependency in the context. +The function +.Fn snmp_dep_finish +executes SNMP_DEPOP_FINISH for all dependencies. +.Sh DIAGNOSTICS +If an error occurs in any of the function an error indication as described +above is returned. +Additionally the functions may call snmp_error on unexpected errors. +.Sh SEE ALSO +.Xr gensnmptree 1 , +.Xr bsnmpd 1 , +.Xr bsnmpclient 3 , +.Xr bsnmplib 3 , +.Xr snmpmod 3 +.Sh STANDARDS +This implementation conforms to the applicable IETF RFCs and ITU-T +recommendations. +.Sh AUTHORS +.An Hartmut Brandt Aq harti@FreeBSD.org Property changes on: vendor/bsnmp/1.13/lib/bsnmpagent.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/bsnmpclient.3 =================================================================== --- vendor/bsnmp/1.13/lib/bsnmpclient.3 (nonexistent) +++ vendor/bsnmp/1.13/lib/bsnmpclient.3 (revision 336778) @@ -0,0 +1,706 @@ +.\" +.\" Copyright (c) 2004-2005 +.\" Hartmut Brandt. +.\" All rights reserved. +.\" Copyright (c) 2001-2003 +.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus). +.\" All rights reserved. +.\" +.\" Author: Harti Brandt +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Begemot: bsnmp/lib/bsnmpclient.3,v 1.12 2005/10/04 08:46:50 brandt_h Exp $ +.\" +.Dd December 31, 2016 +.Dt BSNMPCLIENT 3 +.Os +.Sh NAME +.Nm snmp_client , +.Nm snmp_client_init , +.Nm snmp_client_set_host , +.Nm snmp_client_set_port , +.Nm snmp_send_cb_f , +.Nm snmp_timeout_cb_f , +.Nm snmp_timeout_start_f , +.Nm snmp_timeout_stop_f , +.Nm snmp_open , +.Nm snmp_close , +.Nm snmp_pdu_create , +.Nm snmp_add_binding , +.Nm snmp_pdu_check , +.Nm snmp_pdu_send , +.Nm snmp_oid_append , +.Nm snmp_parse_server , +.Nm snmp_receive , +.Nm snmp_table_cb_f , +.Nm snmp_table_fetch , +.Nm snmp_table_fetch_async , +.Nm snmp_dialog , +.Nm snmp_discover_engine +.Nd "SNMP client library" +.Sh LIBRARY +Begemot SNMP library +.Pq libbsnmp, -lbsnmp +.Sh SYNOPSIS +.In asn1.h +.In snmp.h +.In snmpclient.h +.Ft typedef void +.Fn (*snmp_send_cb_f) "struct snmp_pdu *req" "struct snmp_pdu *resp" "void *uarg" +.Ft typedef void +.Fn (*snmp_timeout_cb_f) "void *uarg" +.Ft typedef void * +.Fn (*snmp_timeout_start_f) "struct timeval *timeout" "snmp_timeout_cb_f callback" "void *uarg" +.Ft typedef void +.Fn (*snmp_timeout_stop_f) "void *timeout_id" +.Vt extern struct snmp_client snmp_client ; +.Ft void +.Fn snmp_client_init "struct snmp_client *client" +.Ft int +.Fn snmp_client_set_host "struct snmp_client *client" "const char *host" +.Ft int +.Fn snmp_client_set_port "struct snmp_client *client" "const char *port" +.Ft int +.Fn snmp_open "const char *host" "const char *port" "const char *read_community" "const char *write_community" +.Ft void +.Fn snmp_close "void" +.Ft void +.Fn snmp_pdu_create "struct snmp_pdu *pdu" "u_int op" +.Ft int +.Fn snmp_add_binding "struct snmp_pdu *pdu" "..." +.Ft int +.Fn snmp_pdu_check "const struct snmp_pdu *req" "const struct snmp_pdu *resp" +.Ft int32_t +.Fn snmp_pdu_send "struct snmp_pdu *pdu" "snmp_send_cb_f func" "void *uarg" +.Ft int +.Fn snmp_oid_append "struct asn_oid *oid" "const char *fmt" "..." +.Ft int +.Fn snmp_parse_server "struct snmp_client *sc" "const char *str" +.Ft int +.Fn snmp_receive "int blocking" +.Ft typedef void +.Fn (*snmp_table_cb_f) "void *list" "void *arg" "int res" +.Ft int +.Fn snmp_table_fetch "const struct snmp_table *descr" "void *list" +.Ft int +.Fn snmp_table_fetch_async "const struct snmp_table *descr" "void *list" "snmp_table_cb_f callback" "void *uarg" +.Ft int +.Fn snmp_dialog "struct snmp_pdu *req" "struct snmp_pdu *resp" +.Ft int +.Fn snmp_discover_engine "void" +.Sh DESCRIPTION +The SNMP library contains routines to easily build SNMP client applications +that use SNMP versions 1, 2 or 3. +Most of the routines use a +.Vt struct snmp_client : +.Bd -literal -offset indent +struct snmp_client { + enum snmp_version version; + int trans; /* which transport to use */ + + /* these two are read-only for the application */ + char *cport; /* port number as string */ + char *chost; /* host name or IP address as string */ + + char read_community[SNMP_COMMUNITY_MAXLEN + 1]; + char write_community[SNMP_COMMUNITY_MAXLEN + 1]; + + /* SNMPv3 specific fields */ + int32_t identifier; + int32_t security_model; + struct snmp_engine engine; + struct snmp_user user; + + /* SNMPv3 Access control - VACM*/ + uint32_t clen; + uint8_t cengine[SNMP_ENGINE_ID_SIZ]; + char cname[SNMP_CONTEXT_NAME_SIZ]; + + struct timeval timeout; + u_int retries; + + int dump_pdus; + + size_t txbuflen; + size_t rxbuflen; + + int fd; + + int32_t next_reqid; + int32_t max_reqid; + int32_t min_reqid; + + char error[SNMP_STRERROR_LEN]; + + snmp_timeout_start_f timeout_start; + snmp_timeout_stop_f timeout_stop; + + char local_path[sizeof(SNMP_LOCAL_PATH)]; +}; +.Ed +.Pp +The fields of this structure are described below. +.Bl -tag -width "timeout_start" +.It Va version +This is the version of SNMP to use. +See +.Xr bsnmplib 3 +for applicable values. +The default version is +.Li SNMP_V2c . +.It Va trans +If this is +.Dv SNMP_TRANS_LOC_DGRAM +a local datagram socket is used. +If it is +.Dv SNMP_TRANS_LOC_STREAM +a local stream socket is used. +For +.Dv SNMP_TRANS_UDP +a UDP socket is created. +It uses the +.Va chost +field as the path to the server's socket for local sockets. +.It Va cport +The SNMP agent's UDP port number. +This may be a symbolic port number (from +.Pa /etc/services ) +or a numeric port number. +If this field is +.Li NULL +(the default) the standard SNMP port is used. +This field should not be changed directly but rather by calling +.Fn snmp_client_set_port . +.It Va chost +The SNMP agent's host name, IP address or +.Ux +domain socket path name. +If this is +.Li NULL +(the default) +.Li localhost +is assumed. +This field should not be changed directly but rather through calling +.Fn snmp_client_set_host . +.It Va read_community +This is the community name to be used for all requests except SET requests. +The default is +.Sq public . +.It Va write_community +The community name to be used for SET requests. +The default is +.Sq private . +.It Va identifier +The message identifier value to be used with SNMPv3 PDUs. Incremented with +each transmitted PDU. +.It Va security_model +The security model to be used with SNMPv3 PDUs. Currently only User-Based +Security model specified by RFC 3414 (value 3) is supported. +.It Va engine +The authoritive SNMP engine parameters to be used with SNMPv3 PDUs. +.It Va user +The USM SNMP user credentials to be used with SNMPv3 PDUs. +.It Va clen +The length of the context engine id to be used with SNMPv3 PDUs. +.It Va cengine +The context engine id to be used with SNMPv3 PDUs. Default is empty. +.It Va cname +The context name to be used with SNMPv3 PDUs. Default is +.Sq "" . +.It Va timeout +The maximum time to wait for responses to requests. +If the time elapses, the request is resent up to +.Va retries +times. +The default is 3 seconds. +.It Va retries +Number of times a request PDU is to be resent. +If set to 0, the request is sent only once. +The default is 3 retransmissions. +.It Va dump_pdus +If set to a non-zero value all received and sent PDUs are dumped via +.Xr snmp_pdu_dump 3 . +The default is not to dump PDUs. +.It Va txbuflen +The encoding buffer size to be allocated for transmitted PDUs. +The default is 10000 octets. +.It Va rxbuflen +The decoding buffer size to be allocated for received PDUs. +This is the size of the maximum PDU that can be received. +The default is 10000 octets. +.It Va fd +After calling +.Fn snmp_open +this is the file socket file descriptor used for sending and receiving PDUs. +.It Va next_reqid +The request id of the next PDU to send. +Used internal by the library. +.It Va max_reqid +The maximum request id to use for outgoing PDUs. +The default is +.Li INT32_MAX . +.It Va min_reqid +The minimum request id to use for outgoing PDUs. +Request ids are allocated linearily starting at +.Va min_reqid +up to +.Va max_reqid . +.It Va error +If an error happens, this field is set to a printable string describing the +error. +.It Va timeout_start +This field must point to a function setting up a one shot timeout. +After the timeout has elapsed, the given callback function must be called +with the user argument. +The +.Fn timeout_start +function must return a +.Vt void * +identifying the timeout. +.It Va timeout_stop +This field must be set to a function that stops a running timeout. +The function will be called with the return value of the corresponding +.Fn timeout_start +function. +.It Va local_path +If in local socket mode, the name of the clients socket. +Not needed by the application. +.El +.Pp +In the current implementation there is a global variable +.Pp +.D1 Vt extern struct snmp_client snmp_client ; +.Pp +that is used by all the library functions. +The first call into the library must be a call to +.Fn snmp_client_init +to initialize this global variable to the default values. +After this call and before calling +.Fn snmp_open +the fields of the variable may be modified by the user. +The modification of the +.Va chost +and +.Va cport +fields should be done only via the functions +.Fn snmp_client_set_host +and +.Fn snmp_client_set_port . +.Pp +The function +.Fn snmp_open +creates a UDP or +.Ux +domain socket and connects it to the agent's IP address and port. +If any of the arguments of the call is not +.Li NULL +the corresponding field in the global +.Va snmp_client +is set from the argument. +Otherwise the values that are already in that variable are used. +The function +.Fn snmp_close +closes the socket, stops all timeouts and frees all dynamically allocated +resources. +.Pp +The next three functions are used to create request PDUs. +The function +.Fn snmp_pdu_create +initializes a PDU of type +.Va op . +It does not allocate space for the PDU itself. +This is the responsibility of the caller. +.Fn snmp_add_binding +adds bindings to the PDU and returns the (zero based) index of the first new +binding. +The arguments are pairs of pointer to the OIDs and syntax constants, +terminated by a NULL. +The call +.Bd -literal -offset indent +snmp_add_binding(&pdu, + &oid1, SNMP_SYNTAX_INTEGER, + &oid2, SNMP_SYNTAX_OCTETSTRING, + NULL); +.Ed +.Pp +adds two new bindings to the PDU and returns the index of the first one. +It is the responsibility of the caller to set the value part of the binding +if necessary. +The functions returns -1 if the maximum number of bindings is exhausted. +The function +.Fn snmp_oid_append +can be used to construct variable OIDs for requests. +It takes a pointer to an +.Vt struct asn_oid +that is to be constructed, a format string, and a number of arguments +the type of which depends on the format string. +The format string is interpreted +character by character in the following way: +.Bl -tag -width ".It Li ( Va N Ns Li )" +.It Li i +This format expects an argument of type +.Vt asn_subid_t +and appends this as a single integer to the OID. +.It Li a +This format expects an argument of type +.Vt struct in_addr +and appends to four parts of the IP address to the OID. +.It Li s +This format expects an argument of type +.Vt const char * +and appends the length of the string (as computed by +.Xr strlen 3 ) +and each of the characters in the string to the OID. +.It ( Va N Ns ) +This format expects no argument. +.Va N +must be a decimal number and is stored into an internal variable +.Va size . +.It Li b +This format expects an argument of type +.Vt const char * +and appends +.Va size +characters from the string to the OID. +The string may contain +.Li NUL +characters. +.It Li c +This format expects two arguments: one of type +.Vt size_t +and one of type +.Vt const u_char * . +The first argument gives the number of bytes to append to the OID from the string +pointed to by the second argument. +.El +.Pp +The function +.Fn snmp_pdu_check +may be used to check a response PDU. +A number of checks are performed +(error code, equal number of bindings, syntaxes and values for SET PDUs). +The function returns +1 if everything is ok, 0 if a NOSUCHNAME or similar +error was detected, -1 if the response PDU had fatal errors +and -2 if +.Fa resp +is +.Li NULL +(a timeout occurred). +.Pp +The function +.Fn snmp_pdu_send +encodes and sends the given PDU. +It records the PDU together with the callback +and user pointers in an internal list and arranges for retransmission if no +response is received. +When a response is received or the retransmission count +is exceeded the callback +.Fa func +is called with the original request PDU, the response PDU and the user argument +.Fa uarg . +If the retransmit count is exceeded, +.Fa func +is called with the original request PDU, the response pointer set to +.Li NULL +and the user argument +.Fa uarg . +The caller should not free the request PDU until the callback function is +called. +The callback function must free the request PDU and the response PDU (if not +.Li NULL ). +.Pp +The function +.Fn snmp_receive +tries to receive a PDU. +If the argument is zero, the function polls to see +whether a packet is available, if the argument is non-zero, the function blocks +until the next packet is received. +The packet is delivered via the usual callback +mechanism (non-response packets are silently dropped). +The function returns 0, if a packet was received and successfully dispatched, +-1 if an error occurred or no packet was available (in polling mode). +.Pp +The next two functions are used to retrieve tables from SNMP agents. +They use +the following input structure, that describes the table: +.Bd -literal -offset indent +struct snmp_table { + struct asn_oid table; + struct asn_oid last_change; + u_int max_iter; + size_t entry_size; + u_int index_size; + uint64_t req_mask; + + struct snmp_table_entry { + asn_subid_t subid; + enum snmp_syntax syntax; + off_t offset; + } entries[]; +}; +.Ed +.Pp +The fields of this structure have the following meaning: +.Bl -tag -width "last_change" +.It Va table +This is the base OID of the table. +.It Va last_change +Some tables have a scalar variable of type TIMETICKS attached to them, +that holds the time when the table was last changed. +This OID should be the OID of this variable (without the \&.0 index). +When the table is retrieved +with multiple GET requests, and the variable changes between two request, +the table fetch is restarted. +.It Va max_iter +Maximum number of tries to fetch the table. +.It Va entry_size +The table fetching routines return a list of structures one for each table +row. +This variable is the size of one structure and used to +.Xr malloc 3 +the structure. +.It Va index_size +This is the number of index columns in the table. +.It Va req_mask +This is a bit mask with a 1 for each table column that is required. +Bit 0 corresponds to the first element (index 0) in the array +.Va entries , +bit 1 to the second (index 1) and so on. +SNMP tables may be sparse. +For sparse columns the bit should not be set. +If the bit for a given column is set and +the column value cannot be retrieved for a given row, the table fetch is +restarted assuming that the table is currently being modified by the agent. +The bits for the index columns are ignored. +.It Va entries +This is a variable sized array of column descriptors. +This array is terminated by an element with syntax +.Li SNMP_SYNTAX_NULL . +The first +.Va index_size +elements describe all the index columns of the table, the rest are normal +columns. +If for the column at +.Ql entries[N] +the expression +.Ql req_mask & (1 << N) +yields true, the column is considered a required column. +The fields of this the array elements have the following meaning: +.Bl -tag -width "syntax" +.It Va subid +This is the OID subid of the column. +This is ignored for index entries. +Index entries are decoded according to the +.Va syntax +field. +.It Va syntax +This is the syntax of the column or index. +A syntax of +.Li SNMP_SYNTAX_NULL +terminates the array. +.It Va offset +This is the starting offset of the value of the column in the return structures. +This field can be set with the ISO-C +.Fn offsetof +macro. +.El +.El +.Pp +Both table fetching functions return TAILQ (see +.Xr queue 3 ) +of structures--one for each table row. +These structures must start with a +.Fn TAILQ_ENTRY +and a +.Vt uint64_t +and are allocated via +.Xr malloc 3 . +The +.Fa list +argument of the table functions must point to a +.Fn TAILQ_HEAD . +The +.Vt uint64_t +fields, usually called +.Va found +is used to indicate which of the columns have been found for the given +row. +It is encoded like the +.Fa req_mask +field. +.Pp +The function +.Fn snmp_table_fetch +synchronously fetches the given table. +If everything is ok 0 is returned. +Otherwise the function returns -1 and sets an appropriate error string. +The function +.Fn snmp_table_fetch_async +fetches the tables asynchronously. +If either the entire table is fetch, or +an error occurs the callback function +.Fa callback +is called with the callers arguments +.Fa list +and +.Fa uarg +and a parameter that is either 0 if the table was fetched, or +-1 if there was an error. +The function itself returns -1 if it could not +initialize fetching of the table. +.Pp +The following table description is used to fetch the ATM interface table: +.Bd -literal -offset indent +/* + * ATM interface table + */ +struct atmif { + TAILQ_ENTRY(atmif) link; + uint64_t found; + int32_t index; + u_char *ifname; + size_t ifnamelen; + uint32_t node_id; + uint32_t pcr; + int32_t media; + uint32_t vpi_bits; + uint32_t vci_bits; + uint32_t max_vpcs; + uint32_t max_vccs; + u_char *esi; + size_t esilen; + int32_t carrier; +}; +TAILQ_HEAD(atmif_list, atmif); + +/* list of all ATM interfaces */ +struct atmif_list atmif_list; + +static const struct snmp_table atmif_table = { + OIDX_begemotAtmIfTable, + OIDX_begemotAtmIfTableLastChange, 2, + sizeof(struct atmif), + 1, 0x7ffULL, + { + { 0, SNMP_SYNTAX_INTEGER, + offsetof(struct atmif, index) }, + { 1, SNMP_SYNTAX_OCTETSTRING, + offsetof(struct atmif, ifname) }, + { 2, SNMP_SYNTAX_GAUGE, + offsetof(struct atmif, node_id) }, + { 3, SNMP_SYNTAX_GAUGE, + offsetof(struct atmif, pcr) }, + { 4, SNMP_SYNTAX_INTEGER, + offsetof(struct atmif, media) }, + { 5, SNMP_SYNTAX_GAUGE, + offsetof(struct atmif, vpi_bits) }, + { 6, SNMP_SYNTAX_GAUGE, + offsetof(struct atmif, vci_bits) }, + { 7, SNMP_SYNTAX_GAUGE, + offsetof(struct atmif, max_vpcs) }, + { 8, SNMP_SYNTAX_GAUGE, + offsetof(struct atmif, max_vccs) }, + { 9, SNMP_SYNTAX_OCTETSTRING, + offsetof(struct atmif, esi) }, + { 10, SNMP_SYNTAX_INTEGER, + offsetof(struct atmif, carrier) }, + { 0, SNMP_SYNTAX_NULL, 0 } + } +}; + +\&... + if (snmp_table_fetch(&atmif_table, &atmif_list) != 0) + errx(1, "AtmIf table: %s", snmp_client.error); +\&... +.Ed +.Pp +The function +.Fn snmp_dialog +is used to execute a synchonuous dialog with the agent. +The request PDU +.Fa req +is sent and the function blocks until the response PDU is received. +Note, +that asynchonuous receives are handled (i.e. callback functions of other send +calls or table fetches may be called while in the function). +The response PDU is returned in +.Fa resp . +If no response could be received after all timeouts and retries, the function +returns -1. +If a response was received 0 is returned. +.Pp +The function +.Fn snmp_discover_engine +is used to discover the authoritative snmpEngineId of a remote SNMPv3 agent. +A request PDU with empty USM user name is sent and the client's engine +parameters are set according to the snmpEngine parameters received in the +response PDU. +If the client is configured to use authentication and/or privacy and the +snmpEngineBoots and/or snmpEngineTime in the response had zero values, an +additional request (possibly encrypted) with the appropriate user credentials +is sent to fetch the missing values. +Note, that the function blocks until the discovery process is completed. +If no response could be received after all timeouts and retries, or the +response contained errors the function returns -1. +If the discovery process was completed 0 is returned. +.Pp +The function +.Fn snmp_parse_server +is used to parse an SNMP server specification string and fill in the +fields of a +.Vt struct snmp_client . +The syntax of a server specification is +.Pp +.D1 [trans::][community@][server][:port] +.Pp +where +.Va trans +is the transport name (one of udp, stream or dgram), +.Va community +is the string to be used for both the read and the write community, +.Va server +is the server's host name in case of UDP and the path name in case +of a local socket, and +.Va port +is the port in case of UDP transport. +The function returns 0 in the case of success and return -1 and sets +the error string in case of an error. +.Sh DIAGNOSTICS +If an error occurs in any of the function an error indication as described +above is returned. +Additionally the function sets a printable error string +in the +.Va error +filed of +.Va snmp_client . +.Sh SEE ALSO +.Xr gensnmptree 1 , +.Xr bsnmpd 1 , +.Xr bsnmpagent 3 , +.Xr bsnmplib 3 +.Sh STANDARDS +This implementation conforms to the applicable IETF RFCs and ITU-T +recommendations. +.Sh AUTHORS +.An Hartmut Brandt Aq harti@FreeBSD.org +.An Kendy Kutzner Aq kutzner@fokus.gmd.de Property changes on: vendor/bsnmp/1.13/lib/bsnmpclient.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/bsnmplib.3 =================================================================== --- vendor/bsnmp/1.13/lib/bsnmplib.3 (nonexistent) +++ vendor/bsnmp/1.13/lib/bsnmplib.3 (revision 336778) @@ -0,0 +1,514 @@ +.\" +.\" Copyright (c) 2010 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" Portions of this documentation were written by Shteryana Sotirova Shopova +.\" under sponsorship from the FreeBSD Foundation. +.\" +.\" Copyright (c) 2004-2005 +.\" Hartmut Brandt. +.\" All rights reserved. +.\" Copyright (c) 2001-2003 +.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus). +.\" All rights reserved. +.\" +.\" Author: Harti Brandt +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Begemot: bsnmp/lib/bsnmplib.3,v 1.9 2005/10/04 08:46:51 brandt_h Exp $ +.\" +.Dd December 31, 2016 +.Dt BSNMPLIB 3 +.Os +.Sh NAME +.Nm snmp_value_free , +.Nm snmp_value_parse , +.Nm snmp_value_copy , +.Nm snmp_pdu_free , +.Nm snmp_pdu_decode , +.Nm snmp_pdu_encode , +.Nm snmp_pdu_decode_header , +.Nm snmp_pdu_decode_scoped , +.Nm snmp_pdu_decode_secmode , +.Nm snmp_pdu_init_secparams , +.Nm snmp_pdu_dump , +.Nm snmp_passwd_to_keys , +.Nm snmp_get_local_keys , +.Nm snmp_calc_keychange , +.Nm TRUTH_MK , +.Nm TRUTH_GET , +.Nm TRUTH_OK +.Nd "SNMP decoding and encoding library" +.Sh LIBRARY +Begemot SNMP library +.Pq libbsnmp, -lbsnmp +.Sh SYNOPSIS +.In bsnmp/asn1.h +.In bsnmp/snmp.h +.Ft void +.Fn snmp_value_free "struct snmp_value *value" +.Ft int +.Fn snmp_value_parse "const char *buf" "enum snmp_syntax" "union snmp_values *value" +.Ft int +.Fn snmp_value_copy "struct snmp_value *to" "const struct snmp_value *from" +.Ft void +.Fn snmp_pdu_free "struct snmp_pdu *value" +.Ft enum snmp_code +.Fn snmp_pdu_decode "struct asn_buf *buf" "struct snmp_pdu *pdu" "int32_t *ip" +.Ft enum snmp_code +.Fn snmp_pdu_encode "struct snmp_pdu *pdu" "struct asn_buf *buf" +.Ft enum snmp_code +.Fn snmp_pdu_decode_header "struct snmp_pdu *pdu" "struct asn_buf *buf" +.Ft enum snmp_code +.Fn snmp_pdu_decode_scoped "struct asn_buf *buf" "struct snmp_pdu *pdu" "int32_t *ip" +.Ft enum snmp_code +.Fn snmp_pdu_decode_secmode "struct asn_buf *buf" "struct snmp_pdu *pdu" +.Ft void +.Fn snmp_pdu_init_secparams "struct snmp_pdu *pdu" +.Ft void +.Fn snmp_pdu_dump "const struct snmp_pdu *pdu" +.Ft enum snmp_code +.Fn snmp_passwd_to_keys "struct snmp_user *user" "char *passwd" +.Ft enum snmp_code +.Fn snmp_get_local_keys "struct snmp_user *user" "uint8_t *eid" "uint32_t elen" +.Ft enum snmp_code +.Fn snmp_calc_keychange "struct snmp_user *user" "uint8_t *keychange" +.Ft int +.Fn TRUTH_MK "F" +.Ft int +.Fn TRUTH_GET "T" +.Ft int +.Fn TRUTH_OK "T" +.Sh DESCRIPTION +The SNMP library contains routines to handle SNMP version 1, 2 and 3 PDUs. +There are several basic structures used throughout the library: +.Bd -literal -offset indent +struct snmp_value { + struct asn_oid var; + enum snmp_syntax syntax; + union snmp_values { + int32_t integer;/* also integer32 */ + struct { + u_int len; + u_char *octets; + } octetstring; + struct asn_oid oid; + u_char ipaddress[4]; + uint32_t uint32; /* also gauge32, counter32, + unsigned32, timeticks */ + uint64_t counter64; + } v; +}; +.Ed +.Pp +This structure represents one variable binding from an SNMP PDU. +The field +.Fa var +is the ASN.1 of the variable that is bound. +.Fa syntax +contains either the syntax code of the value or an exception code for SNMPv2 +and may be one of: +.Bd -literal -offset indent +enum snmp_syntax { + SNMP_SYNTAX_NULL = 0, + SNMP_SYNTAX_INTEGER, /* == INTEGER32 */ + SNMP_SYNTAX_OCTETSTRING, + SNMP_SYNTAX_OID, + SNMP_SYNTAX_IPADDRESS, + SNMP_SYNTAX_COUNTER, + SNMP_SYNTAX_GAUGE, /* == UNSIGNED32 */ + SNMP_SYNTAX_TIMETICKS, + + /* v2 additions */ + SNMP_SYNTAX_COUNTER64, + /* exceptions */ + SNMP_SYNTAX_NOSUCHOBJECT, + SNMP_SYNTAX_NOSUCHINSTANCE, + SNMP_SYNTAX_ENDOFMIBVIEW, +}; +.Ed +The field +.Fa v +holds the actual value depending on +.Fa syntax . +Note, that if +.Fa syntax +is +.Li SNMP_SYNTAX_OCTETSTRING +and +.Fa v.octetstring.len +is not zero, +.Fa v.octetstring.octets +points to a string allocated by +.Xr malloc 3 . +.Bd -literal -offset indent +#define SNMP_ENGINE_ID_SIZ 32 + +struct snmp_engine { + uint8_t engine_id[SNMP_ENGINE_ID_SIZ]; + uint32_t engine_len; + int32_t engine_boots; + int32_t engine_time; + int32_t max_msg_size; +}; +.Ed +.Pp +This structure represents an SNMP engine as specified by the SNMP Management +Architecture described in RFC 3411. +.Bd -literal -offset indent +#define SNMP_ADM_STR32_SIZ (32 + 1) +#define SNMP_AUTH_KEY_SIZ 40 +#define SNMP_PRIV_KEY_SIZ 32 + +enum snmp_usm_level { + SNMP_noAuthNoPriv = 1, + SNMP_authNoPriv = 2, + SNMP_authPriv = 3 +}; + +struct snmp_user { + char sec_name[SNMP_ADM_STR32_SIZ]; + enum snmp_authentication auth_proto; + enum snmp_privacy priv_proto; + uint8_t auth_key[SNMP_AUTH_KEY_SIZ]; + uint8_t priv_key[SNMP_PRIV_KEY_SIZ]; +}; +.Ed +.Pp +This structure represents an SNMPv3 user as specified by the User-based +Security Model (USM) described in RFC 3414. The field +.Fa sec_name +is a human readable string containing the security user name. +.Fa auth_proto +contains the id of the authentication protocol in use by the user and may be one +of: +.Bd -literal -offset indent +enum snmp_authentication { + SNMP_AUTH_NOAUTH = 0, + SNMP_AUTH_HMAC_MD5, + SNMP_AUTH_HMAC_SHA +}; +.Ed +.Fa priv_proto +contains the id of the privacy protocol in use by the user and may be one +of: +.Bd -literal -offset indent +enum snmp_privacy { + SNMP_PRIV_NOPRIV = 0, + SNMP_PRIV_DES = 1, + SNMP_PRIV_AES +}; +.Ed +.Fa auth_key +and +.Fa priv_key +contain the authentication and privacy keys for the user. +.Bd -literal -offset indent +#define SNMP_COMMUNITY_MAXLEN 128 +#define SNMP_MAX_BINDINGS 100 +#define SNMP_CONTEXT_NAME_SIZ (32 + 1) +#define SNMP_TIME_WINDOW 150 + +#define SNMP_USM_AUTH_SIZE 12 +#define SNMP_USM_PRIV_SIZE 8 + +#define SNMP_MSG_AUTH_FLAG 0x1 +#define SNMP_MSG_PRIV_FLAG 0x2 +#define SNMP_MSG_REPORT_FLAG 0x4 + +#define SNMP_MPM_SNMP_V1 0 +#define SNMP_MPM_SNMP_V2c 1 +#define SNMP_MPM_SNMP_V3 3 + +struct snmp_pdu { + char community[SNMP_COMMUNITY_MAXLEN + 1]; + enum snmp_version version; + u_int type; + + /* SNMPv3 PDU header fields */ + int32_t identifier; + uint8_t flags; + int32_t security_model; + struct snmp_engine engine; + + /* Associated USM user parameters */ + struct snmp_user user; + uint8_t msg_digest[SNMP_USM_AUTH_SIZE]; + uint8_t msg_salt[SNMP_USM_PRIV_SIZE]; + + /* View-based Access Model */ + uint32_t context_engine_len; + uint8_t context_engine[SNMP_ENGINE_ID_SIZ]; + char context_name[SNMP_CONTEXT_NAME_SIZ]; + + /* trap only */ + struct asn_oid enterprise; + u_char agent_addr[4]; + int32_t generic_trap; + int32_t specific_trap; + uint32_t time_stamp; + + /* others */ + int32_t request_id; + int32_t error_status; + int32_t error_index; + + /* fixes for encoding */ + size_t outer_len; + size_t scoped_len; + u_char *outer_ptr; + u_char *digest_ptr; + u_char *encrypted_ptr; + u_char *scoped_ptr; + u_char *pdu_ptr; + u_char *vars_ptr; + + + struct snmp_value bindings[SNMP_MAX_BINDINGS]; + u_int nbindings; +}; +.Ed +This structure contains a decoded SNMP PDU. +.Fa version +is one of +.Bd -literal -offset indent +enum snmp_version { + SNMP_Verr = 0, + SNMP_V1 = 1, + SNMP_V2c, + SNMP_V3 +}; +.Ed +and +.Fa type +is the type of the PDU. +.Fa security_model +is the security model used for SNMPv3 PDUs. The only supported +value currently is 3 (User-based Security Model). Additional values for any, +unknown, SNMPv1 and SNMPv2c security models are also enumerated +.Bd -literal -offset indent +enum snmp_secmodel { + SNMP_SECMODEL_ANY = 0, + SNMP_SECMODEL_SNMPv1 = 1, + SNMP_SECMODEL_SNMPv2c = 2, + SNMP_SECMODEL_USM = 3, + SNMP_SECMODEL_UNKNOWN +}; +.Ed +.Pp +The function +.Fn snmp_value_free +is used to free all the dynamic allocated contents of an SNMP value. +It does not free the structure pointed to by +.Fa value +itself. +.Pp +The function +.Fn snmp_value_parse +parses the ASCII representation of an SNMP value into its binary form. +This function is mainly used by the configuration file reader of +.Xr bsnmpd 1 . +.Pp +The function +.Fn snmp_value_copy +makes a deep copy of the value pointed to by +.Fa from +to the structure pointed to by +.Fa to . +It assumes that +.Fa to +is uninitialized and will overwrite its previous contents. +It does not itself allocate the structure pointed to by +.Fa to . +.Pp +The function +.Fn snmp_pdu_free +frees all the dynamically allocated components of the PDU. +It does not itself free the structure pointed to by +.Fa pdu . +.Pp +The function +.Fn snmp_pdu_decode +decodes the PDU pointed to by +.Fa buf +and stores the result into +.Fa pdu . +If an error occurs in a variable binding the (1 based) index of this binding +is stored in the variable pointed to by +.Fa ip . +.Pp +The function +.Fn snmp_pdu_encode +encodes the PDU +.Fa pdu +into the an octetstring in buffer, and if authentication and privacy are used, +calculates a message digest and encrypts the PDU data in the buffer +.Fa buf . +.Pp +The function +.Fn snmp_pdu_decode_header +decodes the header of the PDU pointed to by +.Fa buf . +The uncoded PDU contents remain in the buffer. +.Pp +The function +.Fn snmp_pdu_decode_scoped +decodes the scoped PDU pointed to by +.Fa buf . +.Pp +The function +.Fn snmp_pdu_decode_secmode +verifies the authentication parameter contained in the PDU (if present) and +if the PDU is encrypted, decrypts the PDU contents pointed to by +.Fa buf . +If successful, a plain text scoped PDU is stored in the buffer. +.Pp +The function +.Fn snmp_pdu_init_secparams +calculates the initialization vector for the privacy protocol in use before +the PDU pointed to by +.Fa pdu +may be encrypted or decrypted. +.Pp +The function +.Fn snmp_pdu_dump +dumps the PDU in a human readable form by calling +.Fn snmp_printf . +.Pp +The function +.Fn snmp_passwd_to_keys +calculates a binary private authentication key corresponding to a plain text human +readable password string. The calculated key is placed in the +.Fa auth_key +field of the +.Fa user . +.Pp +The function +.Fn snmp_get_local_keys +calculates a localazied authentication and privacy keys for a specified SNMPv3 +engine. The calculateds keys are placed in the +.Fa auth_key +and +.Fa priv_key +fields of the +.Fa user . +.Pp +The function +.Fn snmp_calc_keychange +calculates a binary key change octet string based on the contents of an old and +a new binary localized key. The rezult is placed in the buffer pointer to by +.Fa keychange +and may be used by an SNMPv3 user who wishes to change his/her password +or localized key. +.Pp +The function +.Fn TRUTH_MK +takes a C truth value (zero or non-zero) and makes an SNMP truth value (2 or 1). +The function +.Fn TRUTH_GET +takes an SNMP truth value and makes a C truth value (0 or 1). +The function +.Fn TRUTH_OK +checks, whether its argument is a legal SNMP truth value. +.Sh DIAGNOSTICS +When an error occurs in any of the function the function pointed to +by the global pointer +.Bd -literal -offset indent +extern void (*snmp_error)(const char *, ...); +.Ed +.Pp +with a +.Xr printf 3 +style format string. +There is a default error handler in the library that prints a message +starting with +.Sq SNMP: +followed by the error message to standard error. +.Pp +The function pointed to by +.Bd -literal -offset indent +extern void (*snmp_printf)(const char *, ...); +.Ed +.Pp +is called by the +.Fn snmp_pdu_dump +function. +The default handler is +.Xr printf 3 . +.Sh ERRORS +.Fn snmp_pdu_decode +will return one of the following return codes: +.Bl -tag -width Er +.It Bq Er SNMP_CODE_OK +Success. +.It Bq Er SNMP_CODE_FAILED +The ASN.1 coding was wrong. +.It Bq Er SNMP_CODE_BADLEN +A variable binding value had a wrong length field. +.It Bq Er SNMP_CODE_OORANGE +A variable binding value was out of the allowed range. +.It Bq Er SNMP_CODE_BADVERS +The PDU is of an unsupported version. +.It Bq Er SNMP_CODE_BADENQ +There was an ASN.1 value with an unsupported tag. +.It Bq Er SNMP_CODE_BADSECLEVEL +The requested securityLevel contained in the PDU is not supported. +.It Bq Er SNMP_CODE_BADDIGEST +The PDU authentication parameter received in the PDU did not match the +calculated message digest. +.It Bq Er SNMP_CODE_EDECRYPT +Error occurred while trying to decrypt the PDU. +.El +.Pp +.Fn snmp_pdu_encode +will return one of the following return codes: +.Bl -tag -width Er +.It Bq Er SNMP_CODE_OK +Success. +.It Bq Er SNMP_CODE_FAILED +Encoding failed. +.El +.Sh SEE ALSO +.Xr gensnmptree 1 , +.Xr bsnmpd 1 , +.Xr bsnmpagent 3 , +.Xr bsnmpclient 3 , +.Xr bsnmplib 3 +.Sh CAVEAT +The SNMPv3 message digests, encryption and decryption, and key routines use +the cryptographic functions from +.Xr crypto 3 . +The library may optionally be built without references to the +.Xr crypto 3 +library. In such case only plain text SNMPv3 PDUs without message digests +may be proccessed correctly. +.Sh STANDARDS +This implementation conforms to the applicable IETF RFCs and ITU-T +recommendations. +.Sh AUTHORS +The Begemot SNMP library was originally written by +.An Hartmut Brandt Aq harti@FreeBSD.org +.Pp +.An Shteryana Shopova Aq syrinx@FreeBSD.org +added support for the SNMPv3 message proccessing and User-Based +Security model message authentication and privacy. Property changes on: vendor/bsnmp/1.13/lib/bsnmplib.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/snmp.c =================================================================== --- vendor/bsnmp/1.13/lib/snmp.c (nonexistent) +++ vendor/bsnmp/1.13/lib/snmp.c (revision 336778) @@ -0,0 +1,1448 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Copyright (c) 2010 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by Shteryana Sotirova Shopova + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/lib/snmp.c,v 1.40 2005/10/04 14:32:42 brandt_h Exp $ + * + * SNMP + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_STDINT_H +#include +#elif defined(HAVE_INTTYPES_H) +#include +#endif +#include +#include + +#include "asn1.h" +#include "snmp.h" +#include "snmppriv.h" + +static void snmp_error_func(const char *, ...); +static void snmp_printf_func(const char *, ...); + +void (*snmp_error)(const char *, ...) = snmp_error_func; +void (*snmp_printf)(const char *, ...) = snmp_printf_func; + +/* + * Get the next variable binding from the list. + * ASN errors on the sequence or the OID are always fatal. + */ +static enum asn_err +get_var_binding(struct asn_buf *b, struct snmp_value *binding) +{ + u_char type; + asn_len_t len, trailer; + enum asn_err err; + + if (asn_get_sequence(b, &len) != ASN_ERR_OK) { + snmp_error("cannot parse varbind header"); + return (ASN_ERR_FAILED); + } + + /* temporary truncate the length so that the parser does not + * eat up bytes behind the sequence in the case the encoding is + * wrong of inner elements. */ + trailer = b->asn_len - len; + b->asn_len = len; + + if (asn_get_objid(b, &binding->var) != ASN_ERR_OK) { + snmp_error("cannot parse binding objid"); + return (ASN_ERR_FAILED); + } + if (asn_get_header(b, &type, &len) != ASN_ERR_OK) { + snmp_error("cannot parse binding value header"); + return (ASN_ERR_FAILED); + } + + switch (type) { + + case ASN_TYPE_NULL: + binding->syntax = SNMP_SYNTAX_NULL; + err = asn_get_null_raw(b, len); + break; + + case ASN_TYPE_INTEGER: + binding->syntax = SNMP_SYNTAX_INTEGER; + err = asn_get_integer_raw(b, len, &binding->v.integer); + break; + + case ASN_TYPE_OCTETSTRING: + binding->syntax = SNMP_SYNTAX_OCTETSTRING; + binding->v.octetstring.octets = malloc(len); + if (binding->v.octetstring.octets == NULL) { + snmp_error("%s", strerror(errno)); + return (ASN_ERR_FAILED); + } + binding->v.octetstring.len = len; + err = asn_get_octetstring_raw(b, len, + binding->v.octetstring.octets, + &binding->v.octetstring.len); + if (ASN_ERR_STOPPED(err)) { + free(binding->v.octetstring.octets); + binding->v.octetstring.octets = NULL; + } + break; + + case ASN_TYPE_OBJID: + binding->syntax = SNMP_SYNTAX_OID; + err = asn_get_objid_raw(b, len, &binding->v.oid); + break; + + case ASN_CLASS_APPLICATION|ASN_APP_IPADDRESS: + binding->syntax = SNMP_SYNTAX_IPADDRESS; + err = asn_get_ipaddress_raw(b, len, binding->v.ipaddress); + break; + + case ASN_CLASS_APPLICATION|ASN_APP_TIMETICKS: + binding->syntax = SNMP_SYNTAX_TIMETICKS; + err = asn_get_uint32_raw(b, len, &binding->v.uint32); + break; + + case ASN_CLASS_APPLICATION|ASN_APP_COUNTER: + binding->syntax = SNMP_SYNTAX_COUNTER; + err = asn_get_uint32_raw(b, len, &binding->v.uint32); + break; + + case ASN_CLASS_APPLICATION|ASN_APP_GAUGE: + binding->syntax = SNMP_SYNTAX_GAUGE; + err = asn_get_uint32_raw(b, len, &binding->v.uint32); + break; + + case ASN_CLASS_APPLICATION|ASN_APP_COUNTER64: + binding->syntax = SNMP_SYNTAX_COUNTER64; + err = asn_get_counter64_raw(b, len, &binding->v.counter64); + break; + + case ASN_CLASS_CONTEXT | ASN_EXCEPT_NOSUCHOBJECT: + binding->syntax = SNMP_SYNTAX_NOSUCHOBJECT; + err = asn_get_null_raw(b, len); + break; + + case ASN_CLASS_CONTEXT | ASN_EXCEPT_NOSUCHINSTANCE: + binding->syntax = SNMP_SYNTAX_NOSUCHINSTANCE; + err = asn_get_null_raw(b, len); + break; + + case ASN_CLASS_CONTEXT | ASN_EXCEPT_ENDOFMIBVIEW: + binding->syntax = SNMP_SYNTAX_ENDOFMIBVIEW; + err = asn_get_null_raw(b, len); + break; + + default: + if ((err = asn_skip(b, len)) == ASN_ERR_OK) + err = ASN_ERR_TAG; + snmp_error("bad binding value type 0x%x", type); + break; + } + + if (ASN_ERR_STOPPED(err)) { + snmp_error("cannot parse binding value"); + return (err); + } + + if (b->asn_len != 0) + snmp_error("ignoring junk at end of binding"); + + b->asn_len = trailer; + + return (err); +} + +/* + * Parse the different PDUs contents. Any ASN error in the outer components + * are fatal. Only errors in variable values may be tolerated. If all + * components can be parsed it returns either ASN_ERR_OK or the first + * error that was found. + */ +enum asn_err +snmp_parse_pdus_hdr(struct asn_buf *b, struct snmp_pdu *pdu, asn_len_t *lenp) +{ + if (pdu->type == SNMP_PDU_TRAP) { + if (asn_get_objid(b, &pdu->enterprise) != ASN_ERR_OK) { + snmp_error("cannot parse trap enterprise"); + return (ASN_ERR_FAILED); + } + if (asn_get_ipaddress(b, pdu->agent_addr) != ASN_ERR_OK) { + snmp_error("cannot parse trap agent address"); + return (ASN_ERR_FAILED); + } + if (asn_get_integer(b, &pdu->generic_trap) != ASN_ERR_OK) { + snmp_error("cannot parse 'generic-trap'"); + return (ASN_ERR_FAILED); + } + if (asn_get_integer(b, &pdu->specific_trap) != ASN_ERR_OK) { + snmp_error("cannot parse 'specific-trap'"); + return (ASN_ERR_FAILED); + } + if (asn_get_timeticks(b, &pdu->time_stamp) != ASN_ERR_OK) { + snmp_error("cannot parse trap 'time-stamp'"); + return (ASN_ERR_FAILED); + } + } else { + if (asn_get_integer(b, &pdu->request_id) != ASN_ERR_OK) { + snmp_error("cannot parse 'request-id'"); + return (ASN_ERR_FAILED); + } + if (asn_get_integer(b, &pdu->error_status) != ASN_ERR_OK) { + snmp_error("cannot parse 'error_status'"); + return (ASN_ERR_FAILED); + } + if (asn_get_integer(b, &pdu->error_index) != ASN_ERR_OK) { + snmp_error("cannot parse 'error_index'"); + return (ASN_ERR_FAILED); + } + } + + if (asn_get_sequence(b, lenp) != ASN_ERR_OK) { + snmp_error("cannot get varlist header"); + return (ASN_ERR_FAILED); + } + + return (ASN_ERR_OK); +} + +static enum asn_err +parse_pdus(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *ip) +{ + asn_len_t len, trailer; + struct snmp_value *v; + enum asn_err err, err1; + + err = snmp_parse_pdus_hdr(b, pdu, &len); + if (ASN_ERR_STOPPED(err)) + return (err); + + trailer = b->asn_len - len; + + v = pdu->bindings; + err = ASN_ERR_OK; + while (b->asn_len != 0) { + if (pdu->nbindings == SNMP_MAX_BINDINGS) { + snmp_error("too many bindings (> %u) in PDU", + SNMP_MAX_BINDINGS); + return (ASN_ERR_FAILED); + } + err1 = get_var_binding(b, v); + if (ASN_ERR_STOPPED(err1)) + return (ASN_ERR_FAILED); + if (err1 != ASN_ERR_OK && err == ASN_ERR_OK) { + err = err1; + *ip = pdu->nbindings + 1; + } + pdu->nbindings++; + v++; + } + + b->asn_len = trailer; + + return (err); +} + + +static enum asn_err +parse_secparams(struct asn_buf *b, struct snmp_pdu *pdu) +{ + asn_len_t octs_len; + u_char buf[256]; /* XXX: calc max possible size here */ + struct asn_buf tb; + + memset(buf, 0, 256); + tb.asn_ptr = buf; + tb.asn_len = 256; + u_int len = 256; + + if (asn_get_octetstring(b, buf, &len) != ASN_ERR_OK) { + snmp_error("cannot parse usm header"); + return (ASN_ERR_FAILED); + } + tb.asn_len = len; + + if (asn_get_sequence(&tb, &octs_len) != ASN_ERR_OK) { + snmp_error("cannot decode usm header"); + return (ASN_ERR_FAILED); + } + + octs_len = SNMP_ENGINE_ID_SIZ; + if (asn_get_octetstring(&tb, (u_char *)&pdu->engine.engine_id, + &octs_len) != ASN_ERR_OK) { + snmp_error("cannot decode msg engine id"); + return (ASN_ERR_FAILED); + } + pdu->engine.engine_len = octs_len; + + if (asn_get_integer(&tb, &pdu->engine.engine_boots) != ASN_ERR_OK) { + snmp_error("cannot decode msg engine boots"); + return (ASN_ERR_FAILED); + } + + if (asn_get_integer(&tb, &pdu->engine.engine_time) != ASN_ERR_OK) { + snmp_error("cannot decode msg engine time"); + return (ASN_ERR_FAILED); + } + + octs_len = SNMP_ADM_STR32_SIZ - 1; + if (asn_get_octetstring(&tb, (u_char *)&pdu->user.sec_name, &octs_len) + != ASN_ERR_OK) { + snmp_error("cannot decode msg user name"); + return (ASN_ERR_FAILED); + } + pdu->user.sec_name[octs_len] = '\0'; + + octs_len = sizeof(pdu->msg_digest); + if (asn_get_octetstring(&tb, (u_char *)&pdu->msg_digest, &octs_len) != + ASN_ERR_OK || ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0 && + octs_len != sizeof(pdu->msg_digest))) { + snmp_error("cannot decode msg authentication param"); + return (ASN_ERR_FAILED); + } + + octs_len = sizeof(pdu->msg_salt); + if (asn_get_octetstring(&tb, (u_char *)&pdu->msg_salt, &octs_len) != + ASN_ERR_OK ||((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0 && + octs_len != sizeof(pdu->msg_salt))) { + snmp_error("cannot decode msg authentication param"); + return (ASN_ERR_FAILED); + } + + if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) { + pdu->digest_ptr = b->asn_ptr - SNMP_USM_AUTH_SIZE; + pdu->digest_ptr -= octs_len + ASN_MAXLENLEN; + } + + return (ASN_ERR_OK); +} + +static enum snmp_code +pdu_encode_secparams(struct asn_buf *b, struct snmp_pdu *pdu) +{ + u_char buf[256], *sptr; + struct asn_buf tb; + size_t auth_off, moved = 0; + + auth_off = 0; + memset(buf, 0, 256); + tb.asn_ptr = buf; + tb.asn_len = 256; + + if (asn_put_temp_header(&tb, (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED), + &sptr) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if (asn_put_octetstring(&tb, (u_char *)pdu->engine.engine_id, + pdu->engine.engine_len) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if (asn_put_integer(&tb, pdu->engine.engine_boots) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if (asn_put_integer(&tb, pdu->engine.engine_time) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if (asn_put_octetstring(&tb, (u_char *)pdu->user.sec_name, + strlen(pdu->user.sec_name)) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) { + auth_off = sizeof(buf) - tb.asn_len + ASN_MAXLENLEN; + if (asn_put_octetstring(&tb, (u_char *)pdu->msg_digest, + sizeof(pdu->msg_digest)) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + } else { + if (asn_put_octetstring(&tb, (u_char *)pdu->msg_digest, 0) + != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + } + + if ((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0) { + if (asn_put_octetstring(&tb, (u_char *)pdu->msg_salt, + sizeof(pdu->msg_salt)) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + } else { + if (asn_put_octetstring(&tb, (u_char *)pdu->msg_salt, 0) + != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + } + + if (asn_commit_header(&tb, sptr, &moved) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) + pdu->digest_ptr = b->asn_ptr + auth_off - moved; + + if (asn_put_octetstring(b, buf, sizeof(buf) - tb.asn_len) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + pdu->digest_ptr += ASN_MAXLENLEN; + + if ((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0 && asn_put_temp_header(b, + ASN_TYPE_OCTETSTRING, &pdu->encrypted_ptr) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + return (SNMP_CODE_OK); +} + +/* + * Decode the PDU except for the variable bindings itself. + * If decoding fails because of a bad binding, but the rest can be + * decoded, ip points to the index of the failed variable (errors + * OORANGE, BADLEN or BADVERS). + */ +enum snmp_code +snmp_pdu_decode(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *ip) +{ + enum snmp_code code; + + if ((code = snmp_pdu_decode_header(b, pdu)) != SNMP_CODE_OK) + return (code); + + if (pdu->version == SNMP_V3) { + if (pdu->security_model != SNMP_SECMODEL_USM) + return (SNMP_CODE_FAILED); + if ((code = snmp_pdu_decode_secmode(b, pdu)) != SNMP_CODE_OK) + return (code); + } + + code = snmp_pdu_decode_scoped(b, pdu, ip); + + switch (code) { + case SNMP_CODE_FAILED: + snmp_pdu_free(pdu); + break; + + case SNMP_CODE_BADENC: + if (pdu->version == SNMP_Verr) + return (SNMP_CODE_BADVERS); + + default: + break; + } + + return (code); +} + +enum snmp_code +snmp_pdu_decode_header(struct asn_buf *b, struct snmp_pdu *pdu) +{ + int32_t version; + u_int octs_len; + asn_len_t len; + + pdu->outer_ptr = b->asn_ptr; + pdu->outer_len = b->asn_len; + + if (asn_get_sequence(b, &len) != ASN_ERR_OK) { + snmp_error("cannot decode pdu header"); + return (SNMP_CODE_FAILED); + } + if (b->asn_len < len) { + snmp_error("outer sequence value too short"); + return (SNMP_CODE_FAILED); + } + if (b->asn_len != len) { + snmp_error("ignoring trailing junk in message"); + b->asn_len = len; + } + + if (asn_get_integer(b, &version) != ASN_ERR_OK) { + snmp_error("cannot decode version"); + return (SNMP_CODE_FAILED); + } + + if (version == 0) + pdu->version = SNMP_V1; + else if (version == 1) + pdu->version = SNMP_V2c; + else if (version == 3) + pdu->version = SNMP_V3; + else { + pdu->version = SNMP_Verr; + snmp_error("unsupported SNMP version"); + return (SNMP_CODE_BADENC); + } + + if (pdu->version == SNMP_V3) { + if (asn_get_sequence(b, &len) != ASN_ERR_OK) { + snmp_error("cannot decode pdu global data header"); + return (SNMP_CODE_FAILED); + } + + if (asn_get_integer(b, &pdu->identifier) != ASN_ERR_OK) { + snmp_error("cannot decode msg indetifier"); + return (SNMP_CODE_FAILED); + } + + if (asn_get_integer(b, &pdu->engine.max_msg_size) + != ASN_ERR_OK) { + snmp_error("cannot decode msg size"); + return (SNMP_CODE_FAILED); + } + + octs_len = 1; + if (asn_get_octetstring(b, (u_char *)&pdu->flags, + &octs_len) != ASN_ERR_OK) { + snmp_error("cannot decode msg flags"); + return (SNMP_CODE_FAILED); + } + + if (asn_get_integer(b, &pdu->security_model) != ASN_ERR_OK) { + snmp_error("cannot decode msg size"); + return (SNMP_CODE_FAILED); + } + + if (pdu->security_model != SNMP_SECMODEL_USM) + return (SNMP_CODE_FAILED); + + if (parse_secparams(b, pdu) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + } else { + octs_len = SNMP_COMMUNITY_MAXLEN; + if (asn_get_octetstring(b, (u_char *)pdu->community, + &octs_len) != ASN_ERR_OK) { + snmp_error("cannot decode community"); + return (SNMP_CODE_FAILED); + } + pdu->community[octs_len] = '\0'; + } + + return (SNMP_CODE_OK); +} + +enum snmp_code +snmp_pdu_decode_scoped(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *ip) +{ + u_char type; + asn_len_t len, trailer; + enum asn_err err; + + if (pdu->version == SNMP_V3) { + if (asn_get_sequence(b, &len) != ASN_ERR_OK) { + snmp_error("cannot decode scoped pdu header"); + return (SNMP_CODE_FAILED); + } + + len = SNMP_ENGINE_ID_SIZ; + if (asn_get_octetstring(b, (u_char *)&pdu->context_engine, + &len) != ASN_ERR_OK) { + snmp_error("cannot decode msg context engine"); + return (SNMP_CODE_FAILED); + } + pdu->context_engine_len = len; + + len = SNMP_CONTEXT_NAME_SIZ; + if (asn_get_octetstring(b, (u_char *)&pdu->context_name, + &len) != ASN_ERR_OK) { + snmp_error("cannot decode msg context name"); + return (SNMP_CODE_FAILED); + } + pdu->context_name[len] = '\0'; + } + + if (asn_get_header(b, &type, &len) != ASN_ERR_OK) { + snmp_error("cannot get pdu header"); + return (SNMP_CODE_FAILED); + } + if ((type & ~ASN_TYPE_MASK) != + (ASN_TYPE_CONSTRUCTED | ASN_CLASS_CONTEXT)) { + snmp_error("bad pdu header tag"); + return (SNMP_CODE_FAILED); + } + pdu->type = type & ASN_TYPE_MASK; + + switch (pdu->type) { + + case SNMP_PDU_GET: + case SNMP_PDU_GETNEXT: + case SNMP_PDU_RESPONSE: + case SNMP_PDU_SET: + break; + + case SNMP_PDU_TRAP: + if (pdu->version != SNMP_V1) { + snmp_error("bad pdu type %u", pdu->type); + return (SNMP_CODE_FAILED); + } + break; + + case SNMP_PDU_GETBULK: + case SNMP_PDU_INFORM: + case SNMP_PDU_TRAP2: + case SNMP_PDU_REPORT: + if (pdu->version == SNMP_V1) { + snmp_error("bad pdu type %u", pdu->type); + return (SNMP_CODE_FAILED); + } + break; + + default: + snmp_error("bad pdu type %u", pdu->type); + return (SNMP_CODE_FAILED); + } + + trailer = b->asn_len - len; + b->asn_len = len; + + err = parse_pdus(b, pdu, ip); + if (ASN_ERR_STOPPED(err)) + return (SNMP_CODE_FAILED); + + if (b->asn_len != 0) + snmp_error("ignoring trailing junk after pdu"); + + b->asn_len = trailer; + + return (SNMP_CODE_OK); +} + +enum snmp_code +snmp_pdu_decode_secmode(struct asn_buf *b, struct snmp_pdu *pdu) +{ + u_char type; + enum snmp_code code; + uint8_t digest[SNMP_USM_AUTH_SIZE]; + + if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH && + (pdu->flags & SNMP_MSG_AUTH_FLAG) == 0) + return (SNMP_CODE_BADSECLEVEL); + + if ((code = snmp_pdu_calc_digest(pdu, digest)) != + SNMP_CODE_OK) + return (SNMP_CODE_FAILED); + + if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH && + memcmp(digest, pdu->msg_digest, sizeof(pdu->msg_digest)) != 0) + return (SNMP_CODE_BADDIGEST); + + if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV && (asn_get_header(b, &type, + &pdu->scoped_len) != ASN_ERR_OK || type != ASN_TYPE_OCTETSTRING)) { + snmp_error("cannot decode encrypted pdu"); + return (SNMP_CODE_FAILED); + } + pdu->scoped_ptr = b->asn_ptr; + + if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV && + (pdu->flags & SNMP_MSG_PRIV_FLAG) == 0) + return (SNMP_CODE_BADSECLEVEL); + + if ((code = snmp_pdu_decrypt(pdu)) != SNMP_CODE_OK) + return (SNMP_CODE_FAILED); + + return (code); +} + +/* + * Check whether what we have is the complete PDU by snooping at the + * enclosing structure header. This returns: + * -1 if there are ASN.1 errors + * 0 if we need more data + * > 0 the length of this PDU + */ +int +snmp_pdu_snoop(const struct asn_buf *b0) +{ + u_int length; + asn_len_t len; + struct asn_buf b = *b0; + + /* <0x10|0x20> */ + + if (b.asn_len == 0) + return (0); + if (b.asn_cptr[0] != (ASN_TYPE_SEQUENCE | ASN_TYPE_CONSTRUCTED)) { + asn_error(&b, "bad sequence type %u", b.asn_cptr[0]); + return (-1); + } + b.asn_len--; + b.asn_cptr++; + + if (b.asn_len == 0) + return (0); + + if (*b.asn_cptr & 0x80) { + /* long length */ + length = *b.asn_cptr++ & 0x7f; + b.asn_len--; + if (length == 0) { + asn_error(&b, "indefinite length not supported"); + return (-1); + } + if (length > ASN_MAXLENLEN) { + asn_error(&b, "long length too long (%u)", length); + return (-1); + } + if (length > b.asn_len) + return (0); + len = 0; + while (length--) { + len = (len << 8) | *b.asn_cptr++; + b.asn_len--; + } + } else { + len = *b.asn_cptr++; + b.asn_len--; + } + + if (len > b.asn_len) + return (0); + + return (len + b.asn_cptr - b0->asn_cptr); +} + +/* + * Encode the SNMP PDU without the variable bindings field. + * We do this the rather uneffective way by + * moving things around and assuming that the length field will never + * use more than 2 bytes. + * We need a number of pointers to apply the fixes afterwards. + */ +enum snmp_code +snmp_pdu_encode_header(struct asn_buf *b, struct snmp_pdu *pdu) +{ + enum asn_err err; + u_char *v3_hdr_ptr; + + if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED), + &pdu->outer_ptr) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if (pdu->version == SNMP_V1) + err = asn_put_integer(b, 0); + else if (pdu->version == SNMP_V2c) + err = asn_put_integer(b, 1); + else if (pdu->version == SNMP_V3) + err = asn_put_integer(b, 3); + else + return (SNMP_CODE_BADVERS); + if (err != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if (pdu->version == SNMP_V3) { + if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE | + ASN_TYPE_CONSTRUCTED), &v3_hdr_ptr) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if (asn_put_integer(b, pdu->identifier) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if (asn_put_integer(b, pdu->engine.max_msg_size) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if (pdu->type != SNMP_PDU_RESPONSE && + pdu->type != SNMP_PDU_TRAP && + pdu->type != SNMP_PDU_TRAP2 && + pdu->type != SNMP_PDU_REPORT) + pdu->flags |= SNMP_MSG_REPORT_FLAG; + + if (asn_put_octetstring(b, (u_char *)&pdu->flags, 1) + != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if (asn_put_integer(b, pdu->security_model) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if (asn_commit_header(b, v3_hdr_ptr, NULL) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if (pdu->security_model != SNMP_SECMODEL_USM) + return (SNMP_CODE_FAILED); + + if (pdu_encode_secparams(b, pdu) != SNMP_CODE_OK) + return (SNMP_CODE_FAILED); + + /* View-based Access Conntrol information */ + if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE | + ASN_TYPE_CONSTRUCTED), &pdu->scoped_ptr) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if (asn_put_octetstring(b, (u_char *)pdu->context_engine, + pdu->context_engine_len) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if (asn_put_octetstring(b, (u_char *)pdu->context_name, + strlen(pdu->context_name)) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + } else { + if (asn_put_octetstring(b, (u_char *)pdu->community, + strlen(pdu->community)) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + } + + if (asn_put_temp_header(b, (ASN_TYPE_CONSTRUCTED | ASN_CLASS_CONTEXT | + pdu->type), &pdu->pdu_ptr) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if (pdu->type == SNMP_PDU_TRAP) { + if (pdu->version != SNMP_V1 || + asn_put_objid(b, &pdu->enterprise) != ASN_ERR_OK || + asn_put_ipaddress(b, pdu->agent_addr) != ASN_ERR_OK || + asn_put_integer(b, pdu->generic_trap) != ASN_ERR_OK || + asn_put_integer(b, pdu->specific_trap) != ASN_ERR_OK || + asn_put_timeticks(b, pdu->time_stamp) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + } else { + if (pdu->version == SNMP_V1 && (pdu->type == SNMP_PDU_GETBULK || + pdu->type == SNMP_PDU_INFORM || + pdu->type == SNMP_PDU_TRAP2 || + pdu->type == SNMP_PDU_REPORT)) + return (SNMP_CODE_FAILED); + + if (asn_put_integer(b, pdu->request_id) != ASN_ERR_OK || + asn_put_integer(b, pdu->error_status) != ASN_ERR_OK || + asn_put_integer(b, pdu->error_index) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + } + + if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED), + &pdu->vars_ptr) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + return (SNMP_CODE_OK); +} + +static enum asn_err +snmp_pdu_fix_padd(struct asn_buf *b, struct snmp_pdu *pdu) +{ + asn_len_t padlen; + + if (pdu->user.priv_proto == SNMP_PRIV_DES && pdu->scoped_len % 8 != 0) { + padlen = 8 - (pdu->scoped_len % 8); + if (asn_pad(b, padlen) != ASN_ERR_OK) + return (ASN_ERR_FAILED); + pdu->scoped_len += padlen; + } + + return (ASN_ERR_OK); +} + +enum snmp_code +snmp_fix_encoding(struct asn_buf *b, struct snmp_pdu *pdu) +{ + size_t moved = 0; + enum snmp_code code; + + if (asn_commit_header(b, pdu->vars_ptr, NULL) != ASN_ERR_OK || + asn_commit_header(b, pdu->pdu_ptr, NULL) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if (pdu->version == SNMP_V3) { + if (asn_commit_header(b, pdu->scoped_ptr, NULL) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + pdu->scoped_len = b->asn_ptr - pdu->scoped_ptr; + if (snmp_pdu_fix_padd(b, pdu) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + if (pdu->security_model != SNMP_SECMODEL_USM) + return (SNMP_CODE_FAILED); + + if (snmp_pdu_encrypt(pdu) != SNMP_CODE_OK) + return (SNMP_CODE_FAILED); + + if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV && + asn_commit_header(b, pdu->encrypted_ptr, NULL) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + } + + if (asn_commit_header(b, pdu->outer_ptr, &moved) != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + pdu->outer_len = b->asn_ptr - pdu->outer_ptr; + pdu->digest_ptr -= moved; + + if (pdu->version == SNMP_V3) { + if ((code = snmp_pdu_calc_digest(pdu, pdu->msg_digest)) != + SNMP_CODE_OK) + return (SNMP_CODE_FAILED); + + if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) + memcpy(pdu->digest_ptr, pdu->msg_digest, + sizeof(pdu->msg_digest)); + } + + return (SNMP_CODE_OK); +} + +/* + * Encode a binding. Caller must ensure, that the syntax is ok for that version. + * Be sure not to cobber b, when something fails. + */ +enum asn_err +snmp_binding_encode(struct asn_buf *b, const struct snmp_value *binding) +{ + u_char *ptr; + enum asn_err err; + struct asn_buf save = *b; + + if ((err = asn_put_temp_header(b, (ASN_TYPE_SEQUENCE | + ASN_TYPE_CONSTRUCTED), &ptr)) != ASN_ERR_OK) { + *b = save; + return (err); + } + + if ((err = asn_put_objid(b, &binding->var)) != ASN_ERR_OK) { + *b = save; + return (err); + } + + switch (binding->syntax) { + + case SNMP_SYNTAX_NULL: + err = asn_put_null(b); + break; + + case SNMP_SYNTAX_INTEGER: + err = asn_put_integer(b, binding->v.integer); + break; + + case SNMP_SYNTAX_OCTETSTRING: + err = asn_put_octetstring(b, binding->v.octetstring.octets, + binding->v.octetstring.len); + break; + + case SNMP_SYNTAX_OID: + err = asn_put_objid(b, &binding->v.oid); + break; + + case SNMP_SYNTAX_IPADDRESS: + err = asn_put_ipaddress(b, binding->v.ipaddress); + break; + + case SNMP_SYNTAX_TIMETICKS: + err = asn_put_uint32(b, ASN_APP_TIMETICKS, binding->v.uint32); + break; + + case SNMP_SYNTAX_COUNTER: + err = asn_put_uint32(b, ASN_APP_COUNTER, binding->v.uint32); + break; + + case SNMP_SYNTAX_GAUGE: + err = asn_put_uint32(b, ASN_APP_GAUGE, binding->v.uint32); + break; + + case SNMP_SYNTAX_COUNTER64: + err = asn_put_counter64(b, binding->v.counter64); + break; + + case SNMP_SYNTAX_NOSUCHOBJECT: + err = asn_put_exception(b, ASN_EXCEPT_NOSUCHOBJECT); + break; + + case SNMP_SYNTAX_NOSUCHINSTANCE: + err = asn_put_exception(b, ASN_EXCEPT_NOSUCHINSTANCE); + break; + + case SNMP_SYNTAX_ENDOFMIBVIEW: + err = asn_put_exception(b, ASN_EXCEPT_ENDOFMIBVIEW); + break; + } + + if (err != ASN_ERR_OK) { + *b = save; + return (err); + } + + err = asn_commit_header(b, ptr, NULL); + if (err != ASN_ERR_OK) { + *b = save; + return (err); + } + + return (ASN_ERR_OK); +} + +/* + * Encode an PDU. + */ +enum snmp_code +snmp_pdu_encode(struct snmp_pdu *pdu, struct asn_buf *resp_b) +{ + u_int idx; + enum snmp_code err; + + if ((err = snmp_pdu_encode_header(resp_b, pdu)) != SNMP_CODE_OK) + return (err); + for (idx = 0; idx < pdu->nbindings; idx++) + if (snmp_binding_encode(resp_b, &pdu->bindings[idx]) + != ASN_ERR_OK) + return (SNMP_CODE_FAILED); + + return (snmp_fix_encoding(resp_b, pdu)); +} + +static void +dump_binding(const struct snmp_value *b) +{ + u_int i; + char buf[ASN_OIDSTRLEN]; + + snmp_printf("%s=", asn_oid2str_r(&b->var, buf)); + switch (b->syntax) { + + case SNMP_SYNTAX_NULL: + snmp_printf("NULL"); + break; + + case SNMP_SYNTAX_INTEGER: + snmp_printf("INTEGER %d", b->v.integer); + break; + + case SNMP_SYNTAX_OCTETSTRING: + snmp_printf("OCTET STRING %lu:", b->v.octetstring.len); + for (i = 0; i < b->v.octetstring.len; i++) + snmp_printf(" %02x", b->v.octetstring.octets[i]); + break; + + case SNMP_SYNTAX_OID: + snmp_printf("OID %s", asn_oid2str_r(&b->v.oid, buf)); + break; + + case SNMP_SYNTAX_IPADDRESS: + snmp_printf("IPADDRESS %u.%u.%u.%u", b->v.ipaddress[0], + b->v.ipaddress[1], b->v.ipaddress[2], b->v.ipaddress[3]); + break; + + case SNMP_SYNTAX_COUNTER: + snmp_printf("COUNTER %u", b->v.uint32); + break; + + case SNMP_SYNTAX_GAUGE: + snmp_printf("GAUGE %u", b->v.uint32); + break; + + case SNMP_SYNTAX_TIMETICKS: + snmp_printf("TIMETICKS %u", b->v.uint32); + break; + + case SNMP_SYNTAX_COUNTER64: + snmp_printf("COUNTER64 %lld", b->v.counter64); + break; + + case SNMP_SYNTAX_NOSUCHOBJECT: + snmp_printf("NoSuchObject"); + break; + + case SNMP_SYNTAX_NOSUCHINSTANCE: + snmp_printf("NoSuchInstance"); + break; + + case SNMP_SYNTAX_ENDOFMIBVIEW: + snmp_printf("EndOfMibView"); + break; + + default: + snmp_printf("UNKNOWN SYNTAX %u", b->syntax); + break; + } +} + +static __inline void +dump_bindings(const struct snmp_pdu *pdu) +{ + u_int i; + + for (i = 0; i < pdu->nbindings; i++) { + snmp_printf(" [%u]: ", i); + dump_binding(&pdu->bindings[i]); + snmp_printf("\n"); + } +} + +static __inline void +dump_notrap(const struct snmp_pdu *pdu) +{ + snmp_printf(" request_id=%d", pdu->request_id); + snmp_printf(" error_status=%d", pdu->error_status); + snmp_printf(" error_index=%d\n", pdu->error_index); + dump_bindings(pdu); +} + +void +snmp_pdu_dump(const struct snmp_pdu *pdu) +{ + char buf[ASN_OIDSTRLEN]; + const char *vers; + static const char *types[] = { + [SNMP_PDU_GET] = "GET", + [SNMP_PDU_GETNEXT] = "GETNEXT", + [SNMP_PDU_RESPONSE] = "RESPONSE", + [SNMP_PDU_SET] = "SET", + [SNMP_PDU_TRAP] = "TRAPv1", + [SNMP_PDU_GETBULK] = "GETBULK", + [SNMP_PDU_INFORM] = "INFORM", + [SNMP_PDU_TRAP2] = "TRAPv2", + [SNMP_PDU_REPORT] = "REPORT", + }; + + if (pdu->version == SNMP_V1) + vers = "SNMPv1"; + else if (pdu->version == SNMP_V2c) + vers = "SNMPv2c"; + else if (pdu->version == SNMP_V3) + vers = "SNMPv3"; + else + vers = "v?"; + + switch (pdu->type) { + case SNMP_PDU_TRAP: + snmp_printf("%s %s '%s'", types[pdu->type], vers, pdu->community); + snmp_printf(" enterprise=%s", asn_oid2str_r(&pdu->enterprise, buf)); + snmp_printf(" agent_addr=%u.%u.%u.%u", pdu->agent_addr[0], + pdu->agent_addr[1], pdu->agent_addr[2], pdu->agent_addr[3]); + snmp_printf(" generic_trap=%d", pdu->generic_trap); + snmp_printf(" specific_trap=%d", pdu->specific_trap); + snmp_printf(" time-stamp=%u\n", pdu->time_stamp); + dump_bindings(pdu); + break; + + case SNMP_PDU_GET: + case SNMP_PDU_GETNEXT: + case SNMP_PDU_RESPONSE: + case SNMP_PDU_SET: + case SNMP_PDU_GETBULK: + case SNMP_PDU_INFORM: + case SNMP_PDU_TRAP2: + case SNMP_PDU_REPORT: + snmp_printf("%s %s '%s'", types[pdu->type], vers, pdu->community); + dump_notrap(pdu); + break; + + default: + snmp_printf("bad pdu type %u\n", pdu->type); + break; + } +} + +void +snmp_value_free(struct snmp_value *value) +{ + + if (value->syntax == SNMP_SYNTAX_OCTETSTRING) { + free(value->v.octetstring.octets); + value->v.octetstring.octets = NULL; + } + value->syntax = SNMP_SYNTAX_NULL; +} + +int +snmp_value_copy(struct snmp_value *to, const struct snmp_value *from) +{ + to->var = from->var; + to->syntax = from->syntax; + + if (from->syntax == SNMP_SYNTAX_OCTETSTRING) { + if ((to->v.octetstring.len = from->v.octetstring.len) == 0) + to->v.octetstring.octets = NULL; + else { + to->v.octetstring.octets = malloc(to->v.octetstring.len); + if (to->v.octetstring.octets == NULL) + return (-1); + (void)memcpy(to->v.octetstring.octets, + from->v.octetstring.octets, to->v.octetstring.len); + } + } else + to->v = from->v; + return (0); +} + +void +snmp_pdu_init_secparams(struct snmp_pdu *pdu) +{ + int32_t rval; + + if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH) + pdu->flags |= SNMP_MSG_AUTH_FLAG; + + switch (pdu->user.priv_proto) { + case SNMP_PRIV_DES: + memcpy(pdu->msg_salt, &pdu->engine.engine_boots, + sizeof(pdu->engine.engine_boots)); + rval = random(); + memcpy(pdu->msg_salt + sizeof(pdu->engine.engine_boots), &rval, + sizeof(int32_t)); + pdu->flags |= SNMP_MSG_PRIV_FLAG; + break; + case SNMP_PRIV_AES: + rval = random(); + memcpy(pdu->msg_salt, &rval, sizeof(int32_t)); + rval = random(); + memcpy(pdu->msg_salt + sizeof(int32_t), &rval, sizeof(int32_t)); + pdu->flags |= SNMP_MSG_PRIV_FLAG; + break; + default: + break; + } +} + +void +snmp_pdu_free(struct snmp_pdu *pdu) +{ + u_int i; + + for (i = 0; i < pdu->nbindings; i++) + snmp_value_free(&pdu->bindings[i]); + pdu->nbindings = 0; +} + +/* + * Parse an ASCII SNMP value into the binary form + */ +int +snmp_value_parse(const char *str, enum snmp_syntax syntax, union snmp_values *v) +{ + char *end; + + switch (syntax) { + + case SNMP_SYNTAX_NULL: + case SNMP_SYNTAX_NOSUCHOBJECT: + case SNMP_SYNTAX_NOSUCHINSTANCE: + case SNMP_SYNTAX_ENDOFMIBVIEW: + if (*str != '\0') + return (-1); + return (0); + + case SNMP_SYNTAX_INTEGER: + v->integer = strtoll(str, &end, 0); + if (*end != '\0') + return (-1); + return (0); + + case SNMP_SYNTAX_OCTETSTRING: + { + u_long len; /* actual length of string */ + u_long alloc; /* allocate length of string */ + u_char *octs; /* actual octets */ + u_long oct; /* actual octet */ + u_char *nocts; /* to avoid memory leak */ + u_char c; /* actual character */ + +# define STUFFC(C) \ + if (alloc == len) { \ + alloc += 100; \ + if ((nocts = realloc(octs, alloc)) == NULL) { \ + free(octs); \ + return (-1); \ + } \ + octs = nocts; \ + } \ + octs[len++] = (C); + + len = alloc = 0; + octs = NULL; + + if (*str == '"') { + str++; + while((c = *str++) != '\0') { + if (c == '"') { + if (*str != '\0') { + free(octs); + return (-1); + } + break; + } + if (c == '\\') { + switch (c = *str++) { + + case '\\': + break; + case 'a': + c = '\a'; + break; + case 'b': + c = '\b'; + break; + case 'f': + c = '\f'; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + case 'v': + c = '\v'; + break; + case 'x': + c = 0; + if (!isxdigit(*str)) + break; + if (isdigit(*str)) + c = *str++ - '0'; + else if (isupper(*str)) + c = *str++ - 'A' + 10; + else + c = *str++ - 'a' + 10; + if (!isxdigit(*str)) + break; + if (isdigit(*str)) + c += *str++ - '0'; + else if (isupper(*str)) + c += *str++ - 'A' + 10; + else + c += *str++ - 'a' + 10; + break; + case '0': case '1': case '2': + case '3': case '4': case '5': + case '6': case '7': + c = *str++ - '0'; + if (*str < '0' || *str > '7') + break; + c = *str++ - '0'; + if (*str < '0' || *str > '7') + break; + c = *str++ - '0'; + break; + default: + break; + } + } + STUFFC(c); + } + } else { + while (*str != '\0') { + oct = strtoul(str, &end, 16); + str = end; + if (oct > 0xff) { + free(octs); + return (-1); + } + STUFFC(oct); + if (*str == ':') + str++; + else if(*str != '\0') { + free(octs); + return (-1); + } + } + } + v->octetstring.octets = octs; + v->octetstring.len = len; + return (0); +# undef STUFFC + } + + case SNMP_SYNTAX_OID: + { + u_long subid; + + v->oid.len = 0; + + for (;;) { + if (v->oid.len == ASN_MAXOIDLEN) + return (-1); + subid = strtoul(str, &end, 10); + str = end; + if (subid > ASN_MAXID) + return (-1); + v->oid.subs[v->oid.len++] = (asn_subid_t)subid; + if (*str == '\0') + break; + if (*str != '.') + return (-1); + str++; + } + return (0); + } + + case SNMP_SYNTAX_IPADDRESS: + { + struct hostent *he; + + if (inet_pton(AF_INET, str, &v->ipaddress) == 1) + return (0); + if ((he = gethostbyname2(str, AF_INET)) == NULL) + return (-1); + if (he->h_addrtype != AF_INET) + return (-1); + + memcpy(v->ipaddress, he->h_addr, sizeof(v->ipaddress)); + + return (0); + } + + case SNMP_SYNTAX_COUNTER: + case SNMP_SYNTAX_GAUGE: + case SNMP_SYNTAX_TIMETICKS: + { + uint64_t sub; + + sub = strtoull(str, &end, 0); + if (*end != '\0' || sub > 0xffffffff) + return (-1); + v->uint32 = (uint32_t)sub; + return (0); + } + + case SNMP_SYNTAX_COUNTER64: + v->counter64 = strtoull(str, &end, 0); + if (*end != '\0') + return (-1); + return (0); + } + abort(); +} + +static void +snmp_error_func(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + fprintf(stderr, "SNMP: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +static void +snmp_printf_func(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} Property changes on: vendor/bsnmp/1.13/lib/snmp.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/snmp.h =================================================================== --- vendor/bsnmp/1.13/lib/snmp.h (nonexistent) +++ vendor/bsnmp/1.13/lib/snmp.h (revision 336778) @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Copyright (c) 2010 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by Shteryana Sotirova Shopova + * under sponsorship from the FreeBSD Foundation. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/lib/snmp.h,v 1.30 2004/08/06 08:46:54 brandt Exp $ + * + * Header file for SNMP functions. + */ +#ifndef snmp_h_ +#define snmp_h_ + +#include + +#define SNMP_COMMUNITY_MAXLEN 128 +#define SNMP_MAX_BINDINGS 100 +#define SNMP_CONTEXT_NAME_SIZ (32 + 1) +#define SNMP_ENGINE_ID_SIZ 32 +#define SNMP_TIME_WINDOW 150 + +enum snmp_syntax { + SNMP_SYNTAX_NULL = 0, + SNMP_SYNTAX_INTEGER, /* == INTEGER32 */ + SNMP_SYNTAX_OCTETSTRING, + SNMP_SYNTAX_OID, + SNMP_SYNTAX_IPADDRESS, + SNMP_SYNTAX_COUNTER, + SNMP_SYNTAX_GAUGE, /* == UNSIGNED32 */ + SNMP_SYNTAX_TIMETICKS, + + /* v2 additions */ + SNMP_SYNTAX_COUNTER64, + SNMP_SYNTAX_NOSUCHOBJECT, /* exception */ + SNMP_SYNTAX_NOSUCHINSTANCE, /* exception */ + SNMP_SYNTAX_ENDOFMIBVIEW, /* exception */ +}; + +struct snmp_value { + struct asn_oid var; + enum snmp_syntax syntax; + union snmp_values { + int32_t integer; /* also integer32 */ + struct { + u_int len; + u_char *octets; + } octetstring; + struct asn_oid oid; + u_char ipaddress[4]; + uint32_t uint32; /* also gauge32, counter32, + unsigned32, timeticks */ + uint64_t counter64; + } v; +}; + +enum snmp_version { + SNMP_Verr = 0, + SNMP_V1 = 1, + SNMP_V2c = 2, + SNMP_V3, +}; + +#define SNMP_MPM_SNMP_V1 0 +#define SNMP_MPM_SNMP_V2c 1 +#define SNMP_MPM_SNMP_V3 3 + +#define SNMP_ADM_STR32_SIZ (32 + 1) +#define SNMP_AUTH_KEY_SIZ 40 +#define SNMP_PRIV_KEY_SIZ 32 +#define SNMP_USM_AUTH_SIZE 12 +#define SNMP_USM_PRIV_SIZE 8 +#define SNMP_AUTH_HMACMD5_KEY_SIZ 16 +#define SNMP_AUTH_HMACSHA_KEY_SIZ 20 +#define SNMP_PRIV_AES_KEY_SIZ 16 +#define SNMP_PRIV_DES_KEY_SIZ 8 + + +enum snmp_secmodel { + SNMP_SECMODEL_ANY = 0, + SNMP_SECMODEL_SNMPv1 = 1, + SNMP_SECMODEL_SNMPv2c = 2, + SNMP_SECMODEL_USM = 3, + SNMP_SECMODEL_UNKNOWN +}; + +enum snmp_usm_level { + SNMP_noAuthNoPriv = 1, + SNMP_authNoPriv = 2, + SNMP_authPriv = 3 +}; + +enum snmp_authentication { + SNMP_AUTH_NOAUTH = 0, + SNMP_AUTH_HMAC_MD5, + SNMP_AUTH_HMAC_SHA +}; + +enum snmp_privacy { + SNMP_PRIV_NOPRIV = 0, + SNMP_PRIV_DES = 1, + SNMP_PRIV_AES +}; + +struct snmp_engine { + uint8_t engine_id[SNMP_ENGINE_ID_SIZ]; + uint32_t engine_len; + int32_t engine_boots; + int32_t engine_time; + int32_t max_msg_size; +}; + +struct snmp_user { + char sec_name[SNMP_ADM_STR32_SIZ]; + enum snmp_authentication auth_proto; + enum snmp_privacy priv_proto; + uint8_t auth_key[SNMP_AUTH_KEY_SIZ]; + uint8_t priv_key[SNMP_PRIV_KEY_SIZ]; +}; + +struct snmp_pdu { + char community[SNMP_COMMUNITY_MAXLEN + 1]; + enum snmp_version version; + u_int type; + + /* SNMPv3 PDU header fields */ + int32_t identifier; + uint8_t flags; + int32_t security_model; + struct snmp_engine engine; + + /* Associated USM user parameters */ + struct snmp_user user; + uint8_t msg_digest[SNMP_USM_AUTH_SIZE]; + uint8_t msg_salt[SNMP_USM_PRIV_SIZE]; + + /* View-based Access Model */ + /* XXX: put in separate structure - conflicts with struct snmp_context */ + uint32_t context_engine_len; + uint8_t context_engine[SNMP_ENGINE_ID_SIZ]; + char context_name[SNMP_CONTEXT_NAME_SIZ]; + + /* trap only */ + struct asn_oid enterprise; + u_char agent_addr[4]; + int32_t generic_trap; + int32_t specific_trap; + uint32_t time_stamp; + + /* others */ + int32_t request_id; + int32_t error_status; + int32_t error_index; + + /* fixes for encoding */ + size_t outer_len; + asn_len_t scoped_len; + u_char *outer_ptr; + u_char *digest_ptr; + u_char *encrypted_ptr; + u_char *scoped_ptr; + u_char *pdu_ptr; + u_char *vars_ptr; + + + struct snmp_value bindings[SNMP_MAX_BINDINGS]; + u_int nbindings; +}; +#define snmp_v1_pdu snmp_pdu + +#define SNMP_PDU_GET 0 +#define SNMP_PDU_GETNEXT 1 +#define SNMP_PDU_RESPONSE 2 +#define SNMP_PDU_SET 3 +#define SNMP_PDU_TRAP 4 /* v1 */ +#define SNMP_PDU_GETBULK 5 /* v2 */ +#define SNMP_PDU_INFORM 6 /* v2 */ +#define SNMP_PDU_TRAP2 7 /* v2 */ +#define SNMP_PDU_REPORT 8 /* v2 */ + +#define SNMP_ERR_NOERROR 0 +#define SNMP_ERR_TOOBIG 1 +#define SNMP_ERR_NOSUCHNAME 2 /* v1 */ +#define SNMP_ERR_BADVALUE 3 /* v1 */ +#define SNMP_ERR_READONLY 4 /* v1 */ +#define SNMP_ERR_GENERR 5 +#define SNMP_ERR_NO_ACCESS 6 /* v2 */ +#define SNMP_ERR_WRONG_TYPE 7 /* v2 */ +#define SNMP_ERR_WRONG_LENGTH 8 /* v2 */ +#define SNMP_ERR_WRONG_ENCODING 9 /* v2 */ +#define SNMP_ERR_WRONG_VALUE 10 /* v2 */ +#define SNMP_ERR_NO_CREATION 11 /* v2 */ +#define SNMP_ERR_INCONS_VALUE 12 /* v2 */ +#define SNMP_ERR_RES_UNAVAIL 13 /* v2 */ +#define SNMP_ERR_COMMIT_FAILED 14 /* v2 */ +#define SNMP_ERR_UNDO_FAILED 15 /* v2 */ +#define SNMP_ERR_AUTH_ERR 16 /* v2 */ +#define SNMP_ERR_NOT_WRITEABLE 17 /* v2 */ +#define SNMP_ERR_INCONS_NAME 18 /* v2 */ + +#define SNMP_TRAP_COLDSTART 0 +#define SNMP_TRAP_WARMSTART 1 +#define SNMP_TRAP_LINKDOWN 2 +#define SNMP_TRAP_LINKUP 3 +#define SNMP_TRAP_AUTHENTICATION_FAILURE 4 +#define SNMP_TRAP_EGP_NEIGHBOR_LOSS 5 +#define SNMP_TRAP_ENTERPRISE 6 + +enum snmp_code { + SNMP_CODE_OK = 0, + SNMP_CODE_FAILED, + SNMP_CODE_BADVERS, + SNMP_CODE_BADLEN, + SNMP_CODE_BADENC, + SNMP_CODE_OORANGE, + SNMP_CODE_BADSECLEVEL, + SNMP_CODE_NOTINTIME, + SNMP_CODE_BADUSER, + SNMP_CODE_BADENGINE, + SNMP_CODE_BADDIGEST, + SNMP_CODE_EDECRYPT +}; + +#define SNMP_MSG_AUTH_FLAG 0x1 +#define SNMP_MSG_PRIV_FLAG 0x2 +#define SNMP_MSG_REPORT_FLAG 0x4 +#define SNMP_MSG_AUTODISCOVER 0x80 + +void snmp_value_free(struct snmp_value *); +int snmp_value_parse(const char *, enum snmp_syntax, union snmp_values *); +int snmp_value_copy(struct snmp_value *, const struct snmp_value *); + +void snmp_pdu_free(struct snmp_pdu *); +void snmp_pdu_init_secparams(struct snmp_pdu *); +enum snmp_code snmp_pdu_decode(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *); +enum snmp_code snmp_pdu_decode_header(struct asn_buf *, struct snmp_pdu *); +enum snmp_code snmp_pdu_decode_scoped(struct asn_buf *, struct snmp_pdu *, int32_t *); +enum snmp_code snmp_pdu_encode(struct snmp_pdu *, struct asn_buf *); +enum snmp_code snmp_pdu_decode_secmode(struct asn_buf *, struct snmp_pdu *); + +int snmp_pdu_snoop(const struct asn_buf *); + +void snmp_pdu_dump(const struct snmp_pdu *pdu); + +enum snmp_code snmp_passwd_to_keys(struct snmp_user *, char *); +enum snmp_code snmp_get_local_keys(struct snmp_user *, uint8_t *, uint32_t); +enum snmp_code snmp_calc_keychange(struct snmp_user *, uint8_t *); + +extern void (*snmp_error)(const char *, ...); +extern void (*snmp_printf)(const char *, ...); + +#define TRUTH_MK(F) ((F) ? 1 : 2) +#define TRUTH_GET(T) (((T) == 1) ? 1 : 0) +#define TRUTH_OK(T) ((T) == 1 || (T) == 2) + +#endif Property changes on: vendor/bsnmp/1.13/lib/snmp.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/snmpagent.c =================================================================== --- vendor/bsnmp/1.13/lib/snmpagent.c (nonexistent) +++ vendor/bsnmp/1.13/lib/snmpagent.c (revision 336778) @@ -0,0 +1,1070 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/lib/snmpagent.c,v 1.20 2005/10/04 11:21:33 brandt_h Exp $ + * + * SNMP Agent functions + */ +#include +#include +#include +#include +#include +#include +#ifdef HAVE_STDINT_H +#include +#elif defined(HAVE_INTTYPES_H) +#include +#endif +#include + +#include "asn1.h" +#include "snmp.h" +#include "snmppriv.h" +#include "snmpagent.h" + +static void snmp_debug_func(const char *fmt, ...); + +void (*snmp_debug)(const char *fmt, ...) = snmp_debug_func; + +struct snmp_node *tree; +u_int tree_size; + +/* + * Structure to hold dependencies during SET processing + * The last two members of this structure must be the + * dependency visible by the user and the user data. + */ +struct depend { + TAILQ_ENTRY(depend) link; + size_t len; /* size of data part */ + snmp_depop_t func; + struct snmp_dependency dep; +#if defined(__GNUC__) && __GNUC__ < 3 + u_char data[0]; +#else + u_char data[]; +#endif +}; +TAILQ_HEAD(depend_list, depend); + +/* + * Set context + */ +struct context { + struct snmp_context ctx; + struct depend_list dlist; + const struct snmp_node *node[SNMP_MAX_BINDINGS]; + struct snmp_scratch scratch[SNMP_MAX_BINDINGS]; + struct depend *depend; +}; + +#define TR(W) (snmp_trace & SNMP_TRACE_##W) +u_int snmp_trace = 0; + +static char oidbuf[ASN_OIDSTRLEN]; + +/* + * Allocate a context + */ +struct snmp_context * +snmp_init_context(void) +{ + struct context *context; + + if ((context = malloc(sizeof(*context))) == NULL) + return (NULL); + + memset(context, 0, sizeof(*context)); + TAILQ_INIT(&context->dlist); + + return (&context->ctx); +} + +/* + * Find a variable for SET/GET and the first GETBULK pass. + * Return the node pointer. If the search fails, set the errp to + * the correct SNMPv2 GET exception code. + */ +static struct snmp_node * +find_node(const struct snmp_value *value, enum snmp_syntax *errp) +{ + struct snmp_node *tp; + + if (TR(FIND)) + snmp_debug("find: searching %s", + asn_oid2str_r(&value->var, oidbuf)); + + /* + * If we have an exact match (the entry in the table is a + * sub-oid from the variable) we have found what we are for. + * If the table oid is higher than the variable, there is no match. + */ + for (tp = tree; tp < tree + tree_size; tp++) { + if (asn_is_suboid(&tp->oid, &value->var)) + goto found; + if (asn_compare_oid(&tp->oid, &value->var) >= 0) + break; + } + + if (TR(FIND)) + snmp_debug("find: no match"); + *errp = SNMP_SYNTAX_NOSUCHOBJECT; + return (NULL); + + found: + /* leafs must have a 0 instance identifier */ + if (tp->type == SNMP_NODE_LEAF && + (value->var.len != tp->oid.len + 1 || + value->var.subs[tp->oid.len] != 0)) { + if (TR(FIND)) + snmp_debug("find: bad leaf index"); + *errp = SNMP_SYNTAX_NOSUCHINSTANCE; + return (NULL); + } + if (TR(FIND)) + snmp_debug("find: found %s", + asn_oid2str_r(&value->var, oidbuf)); + return (tp); +} + +static struct snmp_node * +find_subnode(const struct snmp_value *value) +{ + struct snmp_node *tp; + + for (tp = tree; tp < tree + tree_size; tp++) { + if (asn_is_suboid(&value->var, &tp->oid)) + return (tp); + } + return (NULL); +} + +static void +snmp_pdu_create_response(const struct snmp_pdu *pdu, struct snmp_pdu *resp) +{ + memset(resp, 0, sizeof(*resp)); + strcpy(resp->community, pdu->community); + resp->version = pdu->version; + if (pdu->flags & SNMP_MSG_AUTODISCOVER) + resp->type = SNMP_PDU_REPORT; /* RFC 3414.4 */ + else + resp->type = SNMP_PDU_RESPONSE; + resp->request_id = pdu->request_id; + resp->version = pdu->version; + + if (resp->version != SNMP_V3) + return; + + memcpy(&resp->engine, &pdu->engine, sizeof(pdu->engine)); + memcpy(&resp->user, &pdu->user, sizeof(pdu->user)); + snmp_pdu_init_secparams(resp); + resp->identifier = pdu->identifier; + resp->security_model = pdu->security_model; + resp->context_engine_len = pdu->context_engine_len; + memcpy(resp->context_engine, pdu->context_engine, + resp->context_engine_len); + strlcpy(resp->context_name, pdu->context_name, + sizeof(resp->context_name)); +} + +/* + * Execute a GET operation. The tree is rooted at the global 'root'. + * Build the response PDU on the fly. If the return code is SNMP_RET_ERR + * the pdu error status and index will be set. + */ +enum snmp_ret +snmp_get(struct snmp_pdu *pdu, struct asn_buf *resp_b, + struct snmp_pdu *resp, void *data) +{ + int ret; + u_int i; + struct snmp_node *tp; + enum snmp_syntax except; + struct context context; + enum asn_err err; + + memset(&context, 0, sizeof(context)); + context.ctx.data = data; + + snmp_pdu_create_response(pdu, resp); + + if (snmp_pdu_encode_header(resp_b, resp) != SNMP_CODE_OK) + /* cannot even encode header - very bad */ + return (SNMP_RET_IGN); + + for (i = 0; i < pdu->nbindings; i++) { + resp->bindings[i].var = pdu->bindings[i].var; + if ((tp = find_node(&pdu->bindings[i], &except)) == NULL) { + if (pdu->version == SNMP_V1) { + if (TR(GET)) + snmp_debug("get: nosuchname"); + pdu->error_status = SNMP_ERR_NOSUCHNAME; + pdu->error_index = i + 1; + snmp_pdu_free(resp); + return (SNMP_RET_ERR); + } + if (TR(GET)) + snmp_debug("get: exception %u", except); + resp->bindings[i].syntax = except; + + } else { + /* call the action to fetch the value. */ + resp->bindings[i].syntax = tp->syntax; + ret = (*tp->op)(&context.ctx, &resp->bindings[i], + tp->oid.len, tp->index, SNMP_OP_GET); + if (TR(GET)) + snmp_debug("get: action returns %d", ret); + + if (ret == SNMP_ERR_NOSUCHNAME) { + if (pdu->version == SNMP_V1) { + pdu->error_status = SNMP_ERR_NOSUCHNAME; + pdu->error_index = i + 1; + snmp_pdu_free(resp); + return (SNMP_RET_ERR); + } + if (TR(GET)) + snmp_debug("get: exception noSuchInstance"); + resp->bindings[i].syntax = SNMP_SYNTAX_NOSUCHINSTANCE; + + } else if (ret != SNMP_ERR_NOERROR) { + pdu->error_status = SNMP_ERR_GENERR; + pdu->error_index = i + 1; + snmp_pdu_free(resp); + return (SNMP_RET_ERR); + } + } + resp->nbindings++; + + err = snmp_binding_encode(resp_b, &resp->bindings[i]); + + if (err == ASN_ERR_EOBUF) { + pdu->error_status = SNMP_ERR_TOOBIG; + pdu->error_index = 0; + snmp_pdu_free(resp); + return (SNMP_RET_ERR); + } + if (err != ASN_ERR_OK) { + if (TR(GET)) + snmp_debug("get: binding encoding: %u", err); + pdu->error_status = SNMP_ERR_GENERR; + pdu->error_index = i + 1; + snmp_pdu_free(resp); + return (SNMP_RET_ERR); + } + } + + if (snmp_fix_encoding(resp_b, resp) != SNMP_CODE_OK) { + snmp_debug("get: failed to encode PDU"); + return (SNMP_RET_ERR); + } + + return (SNMP_RET_OK); +} + +static struct snmp_node * +next_node(const struct snmp_value *value, int *pnext) +{ + struct snmp_node *tp; + + if (TR(FIND)) + snmp_debug("next: searching %s", + asn_oid2str_r(&value->var, oidbuf)); + + *pnext = 0; + for (tp = tree; tp < tree + tree_size; tp++) { + if (asn_is_suboid(&tp->oid, &value->var)) { + /* the tree OID is a sub-oid of the requested OID. */ + if (tp->type == SNMP_NODE_LEAF) { + if (tp->oid.len == value->var.len) { + /* request for scalar type */ + if (TR(FIND)) + snmp_debug("next: found scalar %s", + asn_oid2str_r(&tp->oid, oidbuf)); + return (tp); + } + /* try next */ + } else { + if (TR(FIND)) + snmp_debug("next: found column %s", + asn_oid2str_r(&tp->oid, oidbuf)); + return (tp); + } + } else if (asn_is_suboid(&value->var, &tp->oid) || + asn_compare_oid(&tp->oid, &value->var) >= 0) { + if (TR(FIND)) + snmp_debug("next: found %s", + asn_oid2str_r(&tp->oid, oidbuf)); + *pnext = 1; + return (tp); + } + } + + if (TR(FIND)) + snmp_debug("next: failed"); + + return (NULL); +} + +static enum snmp_ret +do_getnext(struct context *context, const struct snmp_value *inb, + struct snmp_value *outb, struct snmp_pdu *pdu) +{ + const struct snmp_node *tp; + int ret, next; + + if ((tp = next_node(inb, &next)) == NULL) + goto eofMib; + + /* retain old variable if we are doing a GETNEXT on an exact + * matched leaf only */ + if (tp->type == SNMP_NODE_LEAF || next) + outb->var = tp->oid; + else + outb->var = inb->var; + + for (;;) { + outb->syntax = tp->syntax; + if (tp->type == SNMP_NODE_LEAF) { + /* make a GET operation */ + outb->var.subs[outb->var.len++] = 0; + ret = (*tp->op)(&context->ctx, outb, tp->oid.len, + tp->index, SNMP_OP_GET); + } else { + /* make a GETNEXT */ + ret = (*tp->op)(&context->ctx, outb, tp->oid.len, + tp->index, SNMP_OP_GETNEXT); + } + if (ret != SNMP_ERR_NOSUCHNAME) { + /* got something */ + if (ret != SNMP_ERR_NOERROR && TR(GETNEXT)) + snmp_debug("getnext: %s returns %u", + asn_oid2str(&outb->var), ret); + break; + } + + /* object has no data - try next */ + if (++tp == tree + tree_size) + break; + + if (TR(GETNEXT)) + snmp_debug("getnext: no data - avancing to %s", + asn_oid2str(&tp->oid)); + + outb->var = tp->oid; + } + + if (ret == SNMP_ERR_NOSUCHNAME) { + eofMib: + outb->var = inb->var; + if (pdu->version == SNMP_V1) { + pdu->error_status = SNMP_ERR_NOSUCHNAME; + return (SNMP_RET_ERR); + } + outb->syntax = SNMP_SYNTAX_ENDOFMIBVIEW; + + } else if (ret != SNMP_ERR_NOERROR) { + pdu->error_status = SNMP_ERR_GENERR; + return (SNMP_RET_ERR); + } + return (SNMP_RET_OK); +} + + +/* + * Execute a GETNEXT operation. The tree is rooted at the global 'root'. + * Build the response PDU on the fly. The return is: + */ +enum snmp_ret +snmp_getnext(struct snmp_pdu *pdu, struct asn_buf *resp_b, + struct snmp_pdu *resp, void *data) +{ + struct context context; + u_int i; + enum asn_err err; + enum snmp_ret result; + + memset(&context, 0, sizeof(context)); + context.ctx.data = data; + + snmp_pdu_create_response(pdu, resp); + + if (snmp_pdu_encode_header(resp_b, resp)) + return (SNMP_RET_IGN); + + for (i = 0; i < pdu->nbindings; i++) { + result = do_getnext(&context, &pdu->bindings[i], + &resp->bindings[i], pdu); + + if (result != SNMP_RET_OK) { + pdu->error_index = i + 1; + snmp_pdu_free(resp); + return (result); + } + + resp->nbindings++; + + err = snmp_binding_encode(resp_b, &resp->bindings[i]); + + if (err == ASN_ERR_EOBUF) { + pdu->error_status = SNMP_ERR_TOOBIG; + pdu->error_index = 0; + snmp_pdu_free(resp); + return (SNMP_RET_ERR); + } + if (err != ASN_ERR_OK) { + if (TR(GET)) + snmp_debug("getnext: binding encoding: %u", err); + pdu->error_status = SNMP_ERR_GENERR; + pdu->error_index = i + 1; + snmp_pdu_free(resp); + return (SNMP_RET_ERR); + } + } + + if (snmp_fix_encoding(resp_b, resp) != SNMP_CODE_OK) { + snmp_debug("getnext: failed to encode PDU"); + return (SNMP_RET_ERR); + } + + return (SNMP_RET_OK); +} + +enum snmp_ret +snmp_getbulk(struct snmp_pdu *pdu, struct asn_buf *resp_b, + struct snmp_pdu *resp, void *data) +{ + struct context context; + u_int i; + int cnt; + u_int non_rep; + int eomib; + enum snmp_ret result; + enum asn_err err; + + memset(&context, 0, sizeof(context)); + context.ctx.data = data; + + snmp_pdu_create_response(pdu, resp); + + if (snmp_pdu_encode_header(resp_b, resp) != SNMP_CODE_OK) + /* cannot even encode header - very bad */ + return (SNMP_RET_IGN); + + if ((non_rep = pdu->error_status) > pdu->nbindings) + non_rep = pdu->nbindings; + + /* non-repeaters */ + for (i = 0; i < non_rep; i++) { + result = do_getnext(&context, &pdu->bindings[i], + &resp->bindings[resp->nbindings], pdu); + + if (result != SNMP_RET_OK) { + pdu->error_index = i + 1; + snmp_pdu_free(resp); + return (result); + } + + err = snmp_binding_encode(resp_b, + &resp->bindings[resp->nbindings++]); + + if (err == ASN_ERR_EOBUF) + goto done; + + if (err != ASN_ERR_OK) { + if (TR(GET)) + snmp_debug("getnext: binding encoding: %u", err); + pdu->error_status = SNMP_ERR_GENERR; + pdu->error_index = i + 1; + snmp_pdu_free(resp); + return (SNMP_RET_ERR); + } + } + + if (non_rep == pdu->nbindings) + goto done; + + /* repeates */ + for (cnt = 0; cnt < pdu->error_index; cnt++) { + eomib = 1; + for (i = non_rep; i < pdu->nbindings; i++) { + + if (resp->nbindings == SNMP_MAX_BINDINGS) + /* PDU is full */ + goto done; + + if (cnt == 0) + result = do_getnext(&context, &pdu->bindings[i], + &resp->bindings[resp->nbindings], pdu); + else + result = do_getnext(&context, + &resp->bindings[resp->nbindings - + (pdu->nbindings - non_rep)], + &resp->bindings[resp->nbindings], pdu); + + if (result != SNMP_RET_OK) { + pdu->error_index = i + 1; + snmp_pdu_free(resp); + return (result); + } + if (resp->bindings[resp->nbindings].syntax != + SNMP_SYNTAX_ENDOFMIBVIEW) + eomib = 0; + + err = snmp_binding_encode(resp_b, + &resp->bindings[resp->nbindings++]); + + if (err == ASN_ERR_EOBUF) + goto done; + + if (err != ASN_ERR_OK) { + if (TR(GET)) + snmp_debug("getnext: binding encoding: %u", err); + pdu->error_status = SNMP_ERR_GENERR; + pdu->error_index = i + 1; + snmp_pdu_free(resp); + return (SNMP_RET_ERR); + } + } + if (eomib) + break; + } + + done: + if (snmp_fix_encoding(resp_b, resp) != SNMP_CODE_OK) { + snmp_debug("getnext: failed to encode PDU"); + return (SNMP_RET_ERR); + } + + return (SNMP_RET_OK); +} + +/* + * Rollback a SET operation. Failed index is 'i'. + */ +static void +rollback(struct context *context, struct snmp_pdu *pdu, u_int i) +{ + struct snmp_value *b; + const struct snmp_node *np; + int ret; + + while (i-- > 0) { + b = &pdu->bindings[i]; + np = context->node[i]; + + context->ctx.scratch = &context->scratch[i]; + + ret = (*np->op)(&context->ctx, b, np->oid.len, np->index, + SNMP_OP_ROLLBACK); + + if (ret != SNMP_ERR_NOERROR) { + snmp_error("set: rollback failed (%d) on variable %s " + "index %u", ret, asn_oid2str(&b->var), i); + if (pdu->version != SNMP_V1) { + pdu->error_status = SNMP_ERR_UNDO_FAILED; + pdu->error_index = 0; + } + } + } +} + +/* + * Commit dependencies. + */ +int +snmp_dep_commit(struct snmp_context *ctx) +{ + struct context *context = (struct context *)ctx; + int ret; + + TAILQ_FOREACH(context->depend, &context->dlist, link) { + ctx->dep = &context->depend->dep; + + if (TR(SET)) + snmp_debug("set: dependency commit %s", + asn_oid2str(&ctx->dep->obj)); + + ret = context->depend->func(ctx, ctx->dep, SNMP_DEPOP_COMMIT); + + if (ret != SNMP_ERR_NOERROR) { + if (TR(SET)) + snmp_debug("set: dependency failed %d", ret); + return (ret); + } + } + return (SNMP_ERR_NOERROR); +} + +/* + * Rollback dependencies + */ +int +snmp_dep_rollback(struct snmp_context *ctx) +{ + struct context *context = (struct context *)ctx; + int ret, ret1; + char objbuf[ASN_OIDSTRLEN]; + char idxbuf[ASN_OIDSTRLEN]; + + ret1 = SNMP_ERR_NOERROR; + while ((context->depend = + TAILQ_PREV(context->depend, depend_list, link)) != NULL) { + ctx->dep = &context->depend->dep; + + if (TR(SET)) + snmp_debug("set: dependency rollback %s", + asn_oid2str(&ctx->dep->obj)); + + ret = context->depend->func(ctx, ctx->dep, SNMP_DEPOP_ROLLBACK); + + if (ret != SNMP_ERR_NOERROR) { + snmp_debug("set: dep rollback returns %u: %s %s", ret, + asn_oid2str_r(&ctx->dep->obj, objbuf), + asn_oid2str_r(&ctx->dep->idx, idxbuf)); + if (ret1 == SNMP_ERR_NOERROR) + ret1 = ret; + } + } + return (ret1); +} + +void +snmp_dep_finish(struct snmp_context *ctx) +{ + struct context *context = (struct context *)ctx; + struct depend *d; + + while ((d = TAILQ_FIRST(&context->dlist)) != NULL) { + ctx->dep = &d->dep; + (void)d->func(ctx, ctx->dep, SNMP_DEPOP_FINISH); + TAILQ_REMOVE(&context->dlist, d, link); + free(d); + } +} + +/* + * Do a SET operation. + */ +enum snmp_ret +snmp_set(struct snmp_pdu *pdu, struct asn_buf *resp_b, + struct snmp_pdu *resp, void *data) +{ + int ret; + u_int i; + enum asn_err asnerr; + struct context context; + const struct snmp_node *np; + struct snmp_value *b; + enum snmp_syntax except; + + memset(&context, 0, sizeof(context)); + TAILQ_INIT(&context.dlist); + context.ctx.data = data; + + snmp_pdu_create_response(pdu, resp); + + if (snmp_pdu_encode_header(resp_b, resp)) + return (SNMP_RET_IGN); + + /* + * 1. Find all nodes, check that they are writeable and + * that the syntax is ok, copy over the binding to the response. + */ + for (i = 0; i < pdu->nbindings; i++) { + b = &pdu->bindings[i]; + + if ((np = context.node[i] = find_node(b, &except)) == NULL) { + /* not found altogether or LEAF with wrong index */ + if (TR(SET)) + snmp_debug("set: node not found %s", + asn_oid2str_r(&b->var, oidbuf)); + if (pdu->version == SNMP_V1) { + pdu->error_index = i + 1; + pdu->error_status = SNMP_ERR_NOSUCHNAME; + } else if ((np = find_subnode(b)) != NULL) { + /* 2. intermediate object */ + pdu->error_index = i + 1; + pdu->error_status = SNMP_ERR_NOT_WRITEABLE; + } else if (except == SNMP_SYNTAX_NOSUCHOBJECT) { + pdu->error_index = i + 1; + pdu->error_status = SNMP_ERR_NO_ACCESS; + } else { + pdu->error_index = i + 1; + pdu->error_status = SNMP_ERR_NO_CREATION; + } + snmp_pdu_free(resp); + return (SNMP_RET_ERR); + } + /* + * 2. write/createable? + * Can check this for leafs only, because in v2 we have + * to differentiate between NOT_WRITEABLE and NO_CREATION + * and only the action routine for COLUMNS knows, whether + * a column exists. + */ + if (np->type == SNMP_NODE_LEAF && + !(np->flags & SNMP_NODE_CANSET)) { + if (pdu->version == SNMP_V1) { + pdu->error_index = i + 1; + pdu->error_status = SNMP_ERR_NOSUCHNAME; + } else { + pdu->error_index = i + 1; + pdu->error_status = SNMP_ERR_NOT_WRITEABLE; + } + snmp_pdu_free(resp); + return (SNMP_RET_ERR); + } + /* + * 3. Ensure the right syntax + */ + if (np->syntax != b->syntax) { + if (pdu->version == SNMP_V1) { + pdu->error_index = i + 1; + pdu->error_status = SNMP_ERR_BADVALUE; /* v2: wrongType */ + } else { + pdu->error_index = i + 1; + pdu->error_status = SNMP_ERR_WRONG_TYPE; + } + snmp_pdu_free(resp); + return (SNMP_RET_ERR); + } + /* + * 4. Copy binding + */ + if (snmp_value_copy(&resp->bindings[i], b)) { + pdu->error_index = i + 1; + pdu->error_status = SNMP_ERR_GENERR; + snmp_pdu_free(resp); + return (SNMP_RET_ERR); + } + asnerr = snmp_binding_encode(resp_b, &resp->bindings[i]); + if (asnerr == ASN_ERR_EOBUF) { + pdu->error_index = i + 1; + pdu->error_status = SNMP_ERR_TOOBIG; + snmp_pdu_free(resp); + return (SNMP_RET_ERR); + } else if (asnerr != ASN_ERR_OK) { + pdu->error_index = i + 1; + pdu->error_status = SNMP_ERR_GENERR; + snmp_pdu_free(resp); + return (SNMP_RET_ERR); + } + resp->nbindings++; + } + + context.ctx.code = SNMP_RET_OK; + + /* + * 2. Call the SET method for each node. If a SET fails, rollback + * everything. Map error codes depending on the version. + */ + for (i = 0; i < pdu->nbindings; i++) { + b = &pdu->bindings[i]; + np = context.node[i]; + + context.ctx.var_index = i + 1; + context.ctx.scratch = &context.scratch[i]; + + ret = (*np->op)(&context.ctx, b, np->oid.len, np->index, + SNMP_OP_SET); + + if (TR(SET)) + snmp_debug("set: action %s returns %d", np->name, ret); + + if (pdu->version == SNMP_V1) { + switch (ret) { + case SNMP_ERR_NO_ACCESS: + ret = SNMP_ERR_NOSUCHNAME; + break; + case SNMP_ERR_WRONG_TYPE: + /* should no happen */ + ret = SNMP_ERR_BADVALUE; + break; + case SNMP_ERR_WRONG_LENGTH: + ret = SNMP_ERR_BADVALUE; + break; + case SNMP_ERR_WRONG_ENCODING: + /* should not happen */ + ret = SNMP_ERR_BADVALUE; + break; + case SNMP_ERR_WRONG_VALUE: + ret = SNMP_ERR_BADVALUE; + break; + case SNMP_ERR_NO_CREATION: + ret = SNMP_ERR_NOSUCHNAME; + break; + case SNMP_ERR_INCONS_VALUE: + ret = SNMP_ERR_BADVALUE; + break; + case SNMP_ERR_RES_UNAVAIL: + ret = SNMP_ERR_GENERR; + break; + case SNMP_ERR_COMMIT_FAILED: + ret = SNMP_ERR_GENERR; + break; + case SNMP_ERR_UNDO_FAILED: + ret = SNMP_ERR_GENERR; + break; + case SNMP_ERR_AUTH_ERR: + /* should not happen */ + ret = SNMP_ERR_GENERR; + break; + case SNMP_ERR_NOT_WRITEABLE: + ret = SNMP_ERR_NOSUCHNAME; + break; + case SNMP_ERR_INCONS_NAME: + ret = SNMP_ERR_BADVALUE; + break; + } + } + if (ret != SNMP_ERR_NOERROR) { + pdu->error_index = i + 1; + pdu->error_status = ret; + + rollback(&context, pdu, i); + snmp_pdu_free(resp); + + context.ctx.code = SNMP_RET_ERR; + + goto errout; + } + } + + /* + * 3. Call dependencies + */ + if (TR(SET)) + snmp_debug("set: set operations ok"); + + if ((ret = snmp_dep_commit(&context.ctx)) != SNMP_ERR_NOERROR) { + pdu->error_status = ret; + pdu->error_index = context.ctx.var_index; + + if ((ret = snmp_dep_rollback(&context.ctx)) != SNMP_ERR_NOERROR) { + if (pdu->version != SNMP_V1) { + pdu->error_status = SNMP_ERR_UNDO_FAILED; + pdu->error_index = 0; + } + } + rollback(&context, pdu, i); + snmp_pdu_free(resp); + + context.ctx.code = SNMP_RET_ERR; + + goto errout; + } + + /* + * 4. Commit and copy values from the original packet to the response. + * This is not the commit operation from RFC 1905 but rather an + * 'FREE RESOURCES' operation. It shouldn't fail. + */ + if (TR(SET)) + snmp_debug("set: commiting"); + + for (i = 0; i < pdu->nbindings; i++) { + b = &resp->bindings[i]; + np = context.node[i]; + + context.ctx.var_index = i + 1; + context.ctx.scratch = &context.scratch[i]; + + ret = (*np->op)(&context.ctx, b, np->oid.len, np->index, + SNMP_OP_COMMIT); + + if (ret != SNMP_ERR_NOERROR) + snmp_error("set: commit failed (%d) on" + " variable %s index %u", ret, + asn_oid2str_r(&b->var, oidbuf), i); + } + + if (snmp_fix_encoding(resp_b, resp) != SNMP_CODE_OK) { + snmp_error("set: fix_encoding failed"); + snmp_pdu_free(resp); + context.ctx.code = SNMP_RET_IGN; + } + + /* + * Done + */ + errout: + snmp_dep_finish(&context.ctx); + + if (TR(SET)) + snmp_debug("set: returning %d", context.ctx.code); + + return (context.ctx.code); +} +/* + * Lookup a dependency. If it doesn't exist, create one + */ +struct snmp_dependency * +snmp_dep_lookup(struct snmp_context *ctx, const struct asn_oid *obj, + const struct asn_oid *idx, size_t len, snmp_depop_t func) +{ + struct context *context; + struct depend *d; + + context = (struct context *)(void *) + ((char *)ctx - offsetof(struct context, ctx)); + if (TR(DEPEND)) { + snmp_debug("depend: looking for %s", asn_oid2str(obj)); + if (idx) + snmp_debug("depend: index is %s", asn_oid2str(idx)); + } + TAILQ_FOREACH(d, &context->dlist, link) + if (asn_compare_oid(obj, &d->dep.obj) == 0 && + ((idx == NULL && d->dep.idx.len == 0) || + (idx != NULL && asn_compare_oid(idx, &d->dep.idx) == 0))) { + if(TR(DEPEND)) + snmp_debug("depend: found"); + return (&d->dep); + } + + if(TR(DEPEND)) + snmp_debug("depend: creating"); + + if ((d = malloc(offsetof(struct depend, dep) + len)) == NULL) + return (NULL); + memset(&d->dep, 0, len); + + d->dep.obj = *obj; + if (idx == NULL) + d->dep.idx.len = 0; + else + d->dep.idx = *idx; + d->len = len; + d->func = func; + + TAILQ_INSERT_TAIL(&context->dlist, d, link); + + return (&d->dep); +} + +/* + * Make an error response from a PDU. We do this without decoding the + * variable bindings. This means we can sent the junk back to a caller + * that has sent us junk in the first place. + */ +enum snmp_ret +snmp_make_errresp(const struct snmp_pdu *pdu, struct asn_buf *pdu_b, + struct asn_buf *resp_b) +{ + u_char type; + asn_len_t len; + struct snmp_pdu resp; + enum asn_err err; + enum snmp_code code; + + snmp_pdu_create_response(pdu, &resp); + + if ((code = snmp_pdu_decode_header(pdu_b, &resp)) != SNMP_CODE_OK) + return (SNMP_RET_IGN); + + if (pdu->version == SNMP_V3) { + if (resp.user.priv_proto != SNMP_PRIV_NOPRIV && + (asn_get_header(pdu_b, &type, &resp.scoped_len) != ASN_ERR_OK + || type != ASN_TYPE_OCTETSTRING)) { + snmp_error("cannot decode encrypted pdu"); + return (SNMP_RET_IGN); + } + + if (asn_get_sequence(pdu_b, &len) != ASN_ERR_OK) { + snmp_error("cannot decode scoped pdu header"); + return (SNMP_RET_IGN); + } + + len = SNMP_ENGINE_ID_SIZ; + if (asn_get_octetstring(pdu_b, (u_char *)resp.context_engine, + &len) != ASN_ERR_OK) { + snmp_error("cannot decode msg context engine"); + return (SNMP_RET_IGN); + } + resp.context_engine_len = len; + len = SNMP_CONTEXT_NAME_SIZ; + if (asn_get_octetstring(pdu_b, (u_char *)resp.context_name, + &len) != ASN_ERR_OK) { + snmp_error("cannot decode msg context name"); + return (SNMP_RET_IGN); + } + resp.context_name[len] = '\0'; + } + + + if (asn_get_header(pdu_b, &type, &len) != ASN_ERR_OK) { + snmp_error("cannot get pdu header"); + return (SNMP_RET_IGN); + } + + if ((type & ~ASN_TYPE_MASK) != + (ASN_TYPE_CONSTRUCTED | ASN_CLASS_CONTEXT)) { + snmp_error("bad pdu header tag"); + return (SNMP_RET_IGN); + } + + err = snmp_parse_pdus_hdr(pdu_b, &resp, &len); + if (ASN_ERR_STOPPED(err)) + return (SNMP_RET_IGN); + if (pdu_b->asn_len < len) + return (SNMP_RET_IGN); + pdu_b->asn_len = len; + + /* now we have the bindings left - construct new message */ + resp.error_status = pdu->error_status; + resp.error_index = pdu->error_index; + resp.type = SNMP_PDU_RESPONSE; + + code = snmp_pdu_encode_header(resp_b, &resp); + if (code != SNMP_CODE_OK) + return (SNMP_RET_IGN); + + if (pdu_b->asn_len > resp_b->asn_len) + /* too short */ + return (SNMP_RET_IGN); + (void)memcpy(resp_b->asn_ptr, pdu_b->asn_cptr, pdu_b->asn_len); + resp_b->asn_len -= pdu_b->asn_len; + resp_b->asn_ptr += pdu_b->asn_len; + + code = snmp_fix_encoding(resp_b, &resp); + if (code != SNMP_CODE_OK) + return (SNMP_RET_IGN); + + return (SNMP_RET_OK); +} + +static void +snmp_debug_func(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); +} Property changes on: vendor/bsnmp/1.13/lib/snmpagent.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/snmpagent.h =================================================================== --- vendor/bsnmp/1.13/lib/snmpagent.h (nonexistent) +++ vendor/bsnmp/1.13/lib/snmpagent.h (revision 336778) @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/lib/snmpagent.h,v 1.13 2004/08/06 08:46:56 brandt Exp $ + * + * Header file for SNMP functions. This requires snmp.h to be included. + */ +#ifndef snmp_agent_h_ +#define snmp_agent_h_ + +struct snmp_dependency; + +enum snmp_ret { + /* OK, generate a response */ + SNMP_RET_OK = 0, + /* Error, ignore packet (no response) */ + SNMP_RET_IGN = 1, + /* Error, generate response from original packet */ + SNMP_RET_ERR = 2 +}; + +/* Semi-Opaque object for SET operations */ +struct snmp_context { + u_int var_index; + struct snmp_scratch *scratch; + struct snmp_dependency *dep; + void *data; /* user data */ + enum snmp_ret code; /* return code */ +}; + +struct snmp_scratch { + void *ptr1; + void *ptr2; + uint32_t int1; + uint32_t int2; +}; + +enum snmp_depop { + SNMP_DEPOP_COMMIT, + SNMP_DEPOP_ROLLBACK, + SNMP_DEPOP_FINISH +}; + +typedef int (*snmp_depop_t)(struct snmp_context *, struct snmp_dependency *, + enum snmp_depop); + +struct snmp_dependency { + struct asn_oid obj; + struct asn_oid idx; +}; + +/* + * The TREE + */ +enum snmp_node_type { + SNMP_NODE_LEAF = 1, + SNMP_NODE_COLUMN +}; + +enum snmp_op { + SNMP_OP_GET = 1, + SNMP_OP_GETNEXT, + SNMP_OP_SET, + SNMP_OP_COMMIT, + SNMP_OP_ROLLBACK, +}; + +typedef int (*snmp_op_t)(struct snmp_context *, struct snmp_value *, + u_int, u_int, enum snmp_op); + +struct snmp_node { + struct asn_oid oid; + const char *name; /* name of the leaf */ + enum snmp_node_type type; /* type of this node */ + enum snmp_syntax syntax; + snmp_op_t op; + u_int flags; + uint32_t index; /* index data */ + void *data; /* application data */ + void *tree_data; /* application data */ +}; +extern struct snmp_node *tree; +extern u_int tree_size; + +#define SNMP_NODE_CANSET 0x0001 /* SET allowed */ + +#define SNMP_INDEXES_MAX 7 +#define SNMP_INDEX_SHIFT 4 +#define SNMP_INDEX_MASK 0xf +#define SNMP_INDEX_COUNT(V) ((V) & SNMP_INDEX_MASK) +#define SNMP_INDEX(V,I) \ + (((V) >> (((I) + 1) * SNMP_INDEX_SHIFT)) & SNMP_INDEX_MASK) + +enum { + SNMP_TRACE_GET = 0x00000001, + SNMP_TRACE_GETNEXT = 0x00000002, + SNMP_TRACE_SET = 0x00000004, + SNMP_TRACE_DEPEND = 0x00000008, + SNMP_TRACE_FIND = 0x00000010, +}; +/* trace flag for the following functions */ +extern u_int snmp_trace; + +/* called to write the trace */ +extern void (*snmp_debug)(const char *fmt, ...); + +enum snmp_ret snmp_get(struct snmp_pdu *pdu, struct asn_buf *resp_b, + struct snmp_pdu *resp, void *); +enum snmp_ret snmp_getnext(struct snmp_pdu *pdu, struct asn_buf *resp_b, + struct snmp_pdu *resp, void *); +enum snmp_ret snmp_getbulk(struct snmp_pdu *pdu, struct asn_buf *resp_b, + struct snmp_pdu *resp, void *); +enum snmp_ret snmp_set(struct snmp_pdu *pdu, struct asn_buf *resp_b, + struct snmp_pdu *resp, void *); + +enum snmp_ret snmp_make_errresp(const struct snmp_pdu *, struct asn_buf *, + struct asn_buf *); + +struct snmp_dependency *snmp_dep_lookup(struct snmp_context *, + const struct asn_oid *, const struct asn_oid *, size_t, snmp_depop_t); + +struct snmp_context *snmp_init_context(void); +int snmp_dep_commit(struct snmp_context *); +int snmp_dep_rollback(struct snmp_context *); +void snmp_dep_finish(struct snmp_context *); + +#endif Property changes on: vendor/bsnmp/1.13/lib/snmpagent.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/snmpclient.c =================================================================== --- vendor/bsnmp/1.13/lib/snmpclient.c (nonexistent) +++ vendor/bsnmp/1.13/lib/snmpclient.c (revision 336778) @@ -0,0 +1,1964 @@ +/* + * Copyright (c) 2004-2005 + * Hartmut Brandt. + * All rights reserved. + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * Kendy Kutzner + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/lib/snmpclient.c,v 1.36 2005/10/06 07:14:58 brandt_h Exp $ + * + * Support functions for SNMP clients. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_STDINT_H +#include +#elif defined(HAVE_INTTYPES_H) +#include +#endif +#include +#ifdef HAVE_ERR_H +#include +#endif + +#include "support.h" +#include "asn1.h" +#include "snmp.h" +#include "snmpclient.h" +#include "snmppriv.h" + +/* global context */ +struct snmp_client snmp_client; + +/* List of all outstanding requests */ +struct sent_pdu { + int reqid; + struct snmp_pdu *pdu; + struct timeval time; + u_int retrycount; + snmp_send_cb_f callback; + void *arg; + void *timeout_id; + LIST_ENTRY(sent_pdu) entries; +}; +LIST_HEAD(sent_pdu_list, sent_pdu); + +static struct sent_pdu_list sent_pdus; + +/* + * Prototype table entry. All C-structure produced by the table function must + * start with these two fields. This relies on the fact, that all TAILQ_ENTRY + * are compatible with each other in the sense implied by ANSI-C. + */ +struct entry { + TAILQ_ENTRY(entry) link; + uint64_t found; +}; +TAILQ_HEAD(table, entry); + +/* + * working list entry. This list is used to hold the Index part of the + * table row's. The entry list and the work list parallel each other. + */ +struct work { + TAILQ_ENTRY(work) link; + struct asn_oid index; +}; +TAILQ_HEAD(worklist, work); + +/* + * Table working data + */ +struct tabwork { + const struct snmp_table *descr; + struct table *table; + struct worklist worklist; + uint32_t last_change; + int first; + u_int iter; + snmp_table_cb_f callback; + void *arg; + struct snmp_pdu pdu; +}; + +/* + * Set the error string + */ +static void +seterr(struct snmp_client *sc, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsnprintf(sc->error, sizeof(sc->error), fmt, ap); + va_end(ap); +} + +/* + * Free the entire table and work list. If table is NULL only the worklist + * is freed. + */ +static void +table_free(struct tabwork *work, int all) +{ + struct work *w; + struct entry *e; + const struct snmp_table_entry *d; + u_int i; + + while ((w = TAILQ_FIRST(&work->worklist)) != NULL) { + TAILQ_REMOVE(&work->worklist, w, link); + free(w); + } + + if (all == 0) + return; + + while ((e = TAILQ_FIRST(work->table)) != NULL) { + for (i = 0; work->descr->entries[i].syntax != SNMP_SYNTAX_NULL; + i++) { + d = &work->descr->entries[i]; + if (d->syntax == SNMP_SYNTAX_OCTETSTRING && + (e->found & ((uint64_t)1 << i))) + free(*(void **)(void *) + ((u_char *)e + d->offset)); + } + TAILQ_REMOVE(work->table, e, link); + free(e); + } +} + +/* + * Find the correct table entry for the given variable. If non exists, + * create one. + */ +static struct entry * +table_find(struct tabwork *work, const struct asn_oid *var) +{ + struct entry *e, *e1; + struct work *w, *w1; + u_int i, p, j; + size_t len; + u_char *ptr; + struct asn_oid oid; + + /* get index */ + asn_slice_oid(&oid, var, work->descr->table.len + 2, var->len); + + e = TAILQ_FIRST(work->table); + w = TAILQ_FIRST(&work->worklist); + while (e != NULL) { + if (asn_compare_oid(&w->index, &oid) == 0) + return (e); + e = TAILQ_NEXT(e, link); + w = TAILQ_NEXT(w, link); + } + + /* Not found create new one */ + if ((e = malloc(work->descr->entry_size)) == NULL) { + seterr(&snmp_client, "no memory for table entry"); + return (NULL); + } + if ((w = malloc(sizeof(*w))) == NULL) { + seterr(&snmp_client, "no memory for table entry"); + free(e); + return (NULL); + } + w->index = oid; + memset(e, 0, work->descr->entry_size); + + /* decode index */ + p = work->descr->table.len + 2; + for (i = 0; i < work->descr->index_size; i++) { + switch (work->descr->entries[i].syntax) { + + case SNMP_SYNTAX_INTEGER: + if (var->len < p + 1) { + seterr(&snmp_client, "bad index: need integer"); + goto err; + } + if (var->subs[p] > INT32_MAX) { + seterr(&snmp_client, + "bad index: integer too large"); + goto err; + } + *(int32_t *)(void *)((u_char *)e + + work->descr->entries[i].offset) = var->subs[p++]; + break; + + case SNMP_SYNTAX_OCTETSTRING: + if (var->len < p + 1) { + seterr(&snmp_client, + "bad index: need string length"); + goto err; + } + len = var->subs[p++]; + if (var->len < p + len) { + seterr(&snmp_client, + "bad index: string too short"); + goto err; + } + if ((ptr = malloc(len + 1)) == NULL) { + seterr(&snmp_client, + "no memory for index string"); + goto err; + } + for (j = 0; j < len; j++) { + if (var->subs[p] > UCHAR_MAX) { + seterr(&snmp_client, + "bad index: char too large"); + free(ptr); + goto err; + } + ptr[j] = var->subs[p++]; + } + ptr[j] = '\0'; + *(u_char **)(void *)((u_char *)e + + work->descr->entries[i].offset) = ptr; + *(size_t *)(void *)((u_char *)e + + work->descr->entries[i].offset + sizeof(u_char *)) + = len; + break; + + case SNMP_SYNTAX_OID: + if (var->len < p + 1) { + seterr(&snmp_client, + "bad index: need oid length"); + goto err; + } + oid.len = var->subs[p++]; + if (var->len < p + oid.len) { + seterr(&snmp_client, + "bad index: oid too short"); + goto err; + } + for (j = 0; j < oid.len; j++) + oid.subs[j] = var->subs[p++]; + *(struct asn_oid *)(void *)((u_char *)e + + work->descr->entries[i].offset) = oid; + break; + + case SNMP_SYNTAX_IPADDRESS: + if (var->len < p + 4) { + seterr(&snmp_client, + "bad index: need ip-address"); + goto err; + } + for (j = 0; j < 4; j++) { + if (var->subs[p] > 0xff) { + seterr(&snmp_client, + "bad index: ipaddress too large"); + goto err; + } + ((u_char *)e + + work->descr->entries[i].offset)[j] = + var->subs[p++]; + } + break; + + case SNMP_SYNTAX_GAUGE: + if (var->len < p + 1) { + seterr(&snmp_client, + "bad index: need unsigned"); + goto err; + } + if (var->subs[p] > UINT32_MAX) { + seterr(&snmp_client, + "bad index: unsigned too large"); + goto err; + } + *(uint32_t *)(void *)((u_char *)e + + work->descr->entries[i].offset) = var->subs[p++]; + break; + + case SNMP_SYNTAX_COUNTER: + case SNMP_SYNTAX_TIMETICKS: + case SNMP_SYNTAX_COUNTER64: + case SNMP_SYNTAX_NULL: + case SNMP_SYNTAX_NOSUCHOBJECT: + case SNMP_SYNTAX_NOSUCHINSTANCE: + case SNMP_SYNTAX_ENDOFMIBVIEW: + abort(); + } + e->found |= (uint64_t)1 << i; + } + + /* link into the correct place */ + e1 = TAILQ_FIRST(work->table); + w1 = TAILQ_FIRST(&work->worklist); + while (e1 != NULL) { + if (asn_compare_oid(&w1->index, &w->index) > 0) + break; + e1 = TAILQ_NEXT(e1, link); + w1 = TAILQ_NEXT(w1, link); + } + if (e1 == NULL) { + TAILQ_INSERT_TAIL(work->table, e, link); + TAILQ_INSERT_TAIL(&work->worklist, w, link); + } else { + TAILQ_INSERT_BEFORE(e1, e, link); + TAILQ_INSERT_BEFORE(w1, w, link); + } + + return (e); + + err: + /* + * Error happend. Free all octet string index parts and the entry + * itself. + */ + for (i = 0; i < work->descr->index_size; i++) { + if (work->descr->entries[i].syntax == SNMP_SYNTAX_OCTETSTRING && + (e->found & ((uint64_t)1 << i))) + free(*(void **)(void *)((u_char *)e + + work->descr->entries[i].offset)); + } + free(e); + free(w); + return (NULL); +} + +/* + * Assign the value + */ +static int +table_value(const struct snmp_table *descr, struct entry *e, + const struct snmp_value *b) +{ + u_int i; + u_char *ptr; + + for (i = descr->index_size; + descr->entries[i].syntax != SNMP_SYNTAX_NULL; i++) + if (descr->entries[i].subid == + b->var.subs[descr->table.len + 1]) + break; + if (descr->entries[i].syntax == SNMP_SYNTAX_NULL) + return (0); + + /* check syntax */ + if (b->syntax != descr->entries[i].syntax) { + seterr(&snmp_client, "bad syntax (%u instead of %u)", b->syntax, + descr->entries[i].syntax); + return (-1); + } + + switch (b->syntax) { + + case SNMP_SYNTAX_INTEGER: + *(int32_t *)(void *)((u_char *)e + descr->entries[i].offset) = + b->v.integer; + break; + + case SNMP_SYNTAX_OCTETSTRING: + if ((ptr = malloc(b->v.octetstring.len + 1)) == NULL) { + seterr(&snmp_client, "no memory for string"); + return (-1); + } + memcpy(ptr, b->v.octetstring.octets, b->v.octetstring.len); + ptr[b->v.octetstring.len] = '\0'; + *(u_char **)(void *)((u_char *)e + descr->entries[i].offset) = + ptr; + *(size_t *)(void *)((u_char *)e + descr->entries[i].offset + + sizeof(u_char *)) = b->v.octetstring.len; + break; + + case SNMP_SYNTAX_OID: + *(struct asn_oid *)(void *)((u_char *)e + descr->entries[i].offset) = + b->v.oid; + break; + + case SNMP_SYNTAX_IPADDRESS: + memcpy((u_char *)e + descr->entries[i].offset, + b->v.ipaddress, 4); + break; + + case SNMP_SYNTAX_COUNTER: + case SNMP_SYNTAX_GAUGE: + case SNMP_SYNTAX_TIMETICKS: + *(uint32_t *)(void *)((u_char *)e + descr->entries[i].offset) = + b->v.uint32; + break; + + case SNMP_SYNTAX_COUNTER64: + *(uint64_t *)(void *)((u_char *)e + descr->entries[i].offset) = + b->v.counter64; + break; + + case SNMP_SYNTAX_NULL: + case SNMP_SYNTAX_NOSUCHOBJECT: + case SNMP_SYNTAX_NOSUCHINSTANCE: + case SNMP_SYNTAX_ENDOFMIBVIEW: + abort(); + } + e->found |= (uint64_t)1 << i; + + return (0); +} + +/* + * Initialize the first PDU to send + */ +static void +table_init_pdu(const struct snmp_table *descr, struct snmp_pdu *pdu) +{ + if (snmp_client.version == SNMP_V1) + snmp_pdu_create(pdu, SNMP_PDU_GETNEXT); + else { + snmp_pdu_create(pdu, SNMP_PDU_GETBULK); + pdu->error_index = 10; + } + if (descr->last_change.len != 0) { + pdu->bindings[pdu->nbindings].syntax = SNMP_SYNTAX_NULL; + pdu->bindings[pdu->nbindings].var = descr->last_change; + pdu->nbindings++; + if (pdu->version != SNMP_V1) + pdu->error_status++; + } + pdu->bindings[pdu->nbindings].var = descr->table; + pdu->bindings[pdu->nbindings].syntax = SNMP_SYNTAX_NULL; + pdu->nbindings++; +} + +/* + * Return code: + * 0 - End Of Table + * -1 - Error + * -2 - Last change changed - again + * +1 - ok, continue + */ +static int +table_check_response(struct tabwork *work, const struct snmp_pdu *resp) +{ + const struct snmp_value *b; + struct entry *e; + + if (resp->error_status != SNMP_ERR_NOERROR) { + if (snmp_client.version == SNMP_V1 && + resp->error_status == SNMP_ERR_NOSUCHNAME && + resp->error_index == + (work->descr->last_change.len == 0) ? 1 : 2) + /* EOT */ + return (0); + /* Error */ + seterr(&snmp_client, "error fetching table: status=%d index=%d", + resp->error_status, resp->error_index); + return (-1); + } + + for (b = resp->bindings; b < resp->bindings + resp->nbindings; b++) { + if (work->descr->last_change.len != 0 && b == resp->bindings) { + if (!asn_is_suboid(&work->descr->last_change, &b->var) || + b->var.len != work->descr->last_change.len + 1 || + b->var.subs[work->descr->last_change.len] != 0) { + seterr(&snmp_client, + "last_change: bad response"); + return (-1); + } + if (b->syntax != SNMP_SYNTAX_TIMETICKS) { + seterr(&snmp_client, + "last_change: bad syntax %u", b->syntax); + return (-1); + } + if (work->first) { + work->last_change = b->v.uint32; + work->first = 0; + + } else if (work->last_change != b->v.uint32) { + if (++work->iter >= work->descr->max_iter) { + seterr(&snmp_client, + "max iteration count exceeded"); + return (-1); + } + table_free(work, 1); + return (-2); + } + + continue; + } + if (!asn_is_suboid(&work->descr->table, &b->var) || + b->syntax == SNMP_SYNTAX_ENDOFMIBVIEW) + return (0); + + if ((e = table_find(work, &b->var)) == NULL) + return (-1); + if (table_value(work->descr, e, b)) + return (-1); + } + return (+1); +} + +/* + * Check table consistency + */ +static int +table_check_cons(struct tabwork *work) +{ + struct entry *e; + + TAILQ_FOREACH(e, work->table, link) + if ((e->found & work->descr->req_mask) != + work->descr->req_mask) { + if (work->descr->last_change.len == 0) { + if (++work->iter >= work->descr->max_iter) { + seterr(&snmp_client, + "max iteration count exceeded"); + return (-1); + } + return (-2); + } + seterr(&snmp_client, "inconsistency detected %llx %llx", + e->found, work->descr->req_mask); + return (-1); + } + return (0); +} + +/* + * Fetch a table. Returns 0 if ok, -1 on errors. + * This is the synchronous variant. + */ +int +snmp_table_fetch(const struct snmp_table *descr, void *list) +{ + struct snmp_pdu resp; + struct tabwork work; + int ret; + + work.descr = descr; + work.table = (struct table *)list; + work.iter = 0; + TAILQ_INIT(work.table); + TAILQ_INIT(&work.worklist); + work.callback = NULL; + work.arg = NULL; + + again: + /* + * We come to this label when the code detects that the table + * has changed while fetching it. + */ + work.first = 1; + work.last_change = 0; + table_init_pdu(descr, &work.pdu); + + for (;;) { + if (snmp_dialog(&work.pdu, &resp)) { + table_free(&work, 1); + return (-1); + } + if ((ret = table_check_response(&work, &resp)) == 0) { + snmp_pdu_free(&resp); + break; + } + if (ret == -1) { + snmp_pdu_free(&resp); + table_free(&work, 1); + return (-1); + } + if (ret == -2) { + snmp_pdu_free(&resp); + goto again; + } + + work.pdu.bindings[work.pdu.nbindings - 1].var = + resp.bindings[resp.nbindings - 1].var; + + snmp_pdu_free(&resp); + } + + if ((ret = table_check_cons(&work)) == -1) { + table_free(&work, 1); + return (-1); + } + if (ret == -2) { + table_free(&work, 1); + goto again; + } + /* + * Free index list + */ + table_free(&work, 0); + return (0); +} + +/* + * Callback for table + */ +static void +table_cb(struct snmp_pdu *req __unused, struct snmp_pdu *resp, void *arg) +{ + struct tabwork *work = arg; + int ret; + + if (resp == NULL) { + /* timeout */ + seterr(&snmp_client, "no response to fetch table request"); + table_free(work, 1); + work->callback(work->table, work->arg, -1); + free(work); + return; + } + + if ((ret = table_check_response(work, resp)) == 0) { + /* EOT */ + snmp_pdu_free(resp); + + if ((ret = table_check_cons(work)) == -1) { + /* error happend */ + table_free(work, 1); + work->callback(work->table, work->arg, -1); + free(work); + return; + } + if (ret == -2) { + /* restart */ + again: + table_free(work, 1); + work->first = 1; + work->last_change = 0; + table_init_pdu(work->descr, &work->pdu); + if (snmp_pdu_send(&work->pdu, table_cb, work) == -1) { + work->callback(work->table, work->arg, -1); + free(work); + return; + } + return; + } + /* + * Free index list + */ + table_free(work, 0); + work->callback(work->table, work->arg, 0); + free(work); + return; + } + + if (ret == -1) { + /* error */ + snmp_pdu_free(resp); + table_free(work, 1); + work->callback(work->table, work->arg, -1); + free(work); + return; + } + + if (ret == -2) { + /* again */ + snmp_pdu_free(resp); + goto again; + } + + /* next part */ + + work->pdu.bindings[work->pdu.nbindings - 1].var = + resp->bindings[resp->nbindings - 1].var; + + snmp_pdu_free(resp); + + if (snmp_pdu_send(&work->pdu, table_cb, work) == -1) { + table_free(work, 1); + work->callback(work->table, work->arg, -1); + free(work); + return; + } +} + +int +snmp_table_fetch_async(const struct snmp_table *descr, void *list, + snmp_table_cb_f func, void *arg) +{ + struct tabwork *work; + + if ((work = malloc(sizeof(*work))) == NULL) { + seterr(&snmp_client, "%s", strerror(errno)); + return (-1); + } + + work->descr = descr; + work->table = (struct table *)list; + work->iter = 0; + TAILQ_INIT(work->table); + TAILQ_INIT(&work->worklist); + + work->callback = func; + work->arg = arg; + + /* + * Start by sending the first PDU + */ + work->first = 1; + work->last_change = 0; + table_init_pdu(descr, &work->pdu); + + if (snmp_pdu_send(&work->pdu, table_cb, work) == -1) { + free(work); + work = NULL; + return (-1); + } + return (0); +} + +/* + * Append an index to an oid + */ +int +snmp_oid_append(struct asn_oid *oid, const char *fmt, ...) +{ + va_list va; + int size; + char *nextptr; + const u_char *str; + size_t len; + struct in_addr ina; + int ret; + + va_start(va, fmt); + + size = 0; + + ret = 0; + while (*fmt != '\0') { + switch (*fmt++) { + case 'i': + /* just an integer more */ + if (oid->len + 1 > ASN_MAXOIDLEN) { + warnx("%s: OID too long for integer", __func__); + ret = -1; + break; + } + oid->subs[oid->len++] = va_arg(va, asn_subid_t); + break; + + case 'a': + /* append an IP address */ + if (oid->len + 4 > ASN_MAXOIDLEN) { + warnx("%s: OID too long for ip-addr", __func__); + ret = -1; + break; + } + ina = va_arg(va, struct in_addr); + ina.s_addr = ntohl(ina.s_addr); + oid->subs[oid->len++] = (ina.s_addr >> 24) & 0xff; + oid->subs[oid->len++] = (ina.s_addr >> 16) & 0xff; + oid->subs[oid->len++] = (ina.s_addr >> 8) & 0xff; + oid->subs[oid->len++] = (ina.s_addr >> 0) & 0xff; + break; + + case 's': + /* append a null-terminated string, + * length is computed */ + str = (const u_char *)va_arg(va, const char *); + len = strlen((const char *)str); + if (oid->len + len + 1 > ASN_MAXOIDLEN) { + warnx("%s: OID too long for string", __func__); + ret = -1; + break; + } + oid->subs[oid->len++] = len; + while (len--) + oid->subs[oid->len++] = *str++; + break; + + case '(': + /* the integer value between ( and ) is stored + * in size */ + size = strtol(fmt, &nextptr, 10); + if (*nextptr != ')') + abort(); + fmt = ++nextptr; + break; + + case 'b': + /* append `size` characters */ + str = (const u_char *)va_arg(va, const char *); + if (oid->len + size > ASN_MAXOIDLEN) { + warnx("%s: OID too long for string", __func__); + ret = -1; + break; + } + while (size--) + oid->subs[oid->len++] = *str++; + break; + + case 'c': + /* get size and the octets from the arguments */ + size = va_arg(va, size_t); + str = va_arg(va, const u_char *); + if (oid->len + size + 1 > ASN_MAXOIDLEN) { + warnx("%s: OID too long for string", __func__); + ret = -1; + break; + } + oid->subs[oid->len++] = size; + while (size--) + oid->subs[oid->len++] = *str++; + break; + + default: + abort(); + } + } + va_end(va); + return (ret); +} + +/* + * Initialize a client structure + */ +void +snmp_client_init(struct snmp_client *c) +{ + memset(c, 0, sizeof(*c)); + + c->version = SNMP_V2c; + c->trans = SNMP_TRANS_UDP; + c->chost = NULL; + c->cport = NULL; + + strcpy(c->read_community, "public"); + strcpy(c->write_community, "private"); + + c->security_model = SNMP_SECMODEL_USM; + strcpy(c->cname, ""); + + c->timeout.tv_sec = 3; + c->timeout.tv_usec = 0; + c->retries = 3; + c->dump_pdus = 0; + c->txbuflen = c->rxbuflen = 10000; + + c->fd = -1; + + c->max_reqid = INT32_MAX; + c->min_reqid = 0; + c->next_reqid = 0; + + c->engine.max_msg_size = 1500; /* XXX */ +} + + +/* + * Open UDP client socket + */ +static int +open_client_udp(const char *host, const char *port) +{ + int error; + char *ptr; + struct addrinfo hints, *res0, *res; + + /* copy host- and portname */ + if (snmp_client.chost == NULL) { + if ((snmp_client.chost = malloc(1 + sizeof(DEFAULT_HOST))) + == NULL) { + seterr(&snmp_client, "%s", strerror(errno)); + return (-1); + } + strcpy(snmp_client.chost, DEFAULT_HOST); + } + if (host != NULL) { + if ((ptr = malloc(1 + strlen(host))) == NULL) { + seterr(&snmp_client, "%s", strerror(errno)); + return (-1); + } + free(snmp_client.chost); + snmp_client.chost = ptr; + strcpy(snmp_client.chost, host); + } + if (snmp_client.cport == NULL) { + if ((snmp_client.cport = malloc(1 + sizeof(DEFAULT_PORT))) + == NULL) { + seterr(&snmp_client, "%s", strerror(errno)); + return (-1); + } + strcpy(snmp_client.cport, DEFAULT_PORT); + } + if (port != NULL) { + if ((ptr = malloc(1 + strlen(port))) == NULL) { + seterr(&snmp_client, "%s", strerror(errno)); + return (-1); + } + free(snmp_client.cport); + snmp_client.cport = ptr; + strcpy(snmp_client.cport, port); + } + + /* open connection */ + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = 0; + error = getaddrinfo(snmp_client.chost, snmp_client.cport, &hints, &res0); + if (error != 0) { + seterr(&snmp_client, "%s: %s", snmp_client.chost, + gai_strerror(error)); + return (-1); + } + res = res0; + for (;;) { + if ((snmp_client.fd = socket(res->ai_family, res->ai_socktype, + res->ai_protocol)) == -1) { + if ((res = res->ai_next) == NULL) { + seterr(&snmp_client, "%s", strerror(errno)); + freeaddrinfo(res0); + return (-1); + } + } else if (connect(snmp_client.fd, res->ai_addr, + res->ai_addrlen) == -1) { + if ((res = res->ai_next) == NULL) { + seterr(&snmp_client, "%s", strerror(errno)); + freeaddrinfo(res0); + (void)close(snmp_client.fd); + snmp_client.fd = -1; + return (-1); + } + } else + break; + } + freeaddrinfo(res0); + return (0); +} + +static void +remove_local(void) +{ + (void)remove(snmp_client.local_path); +} + +/* + * Open local socket + */ +static int +open_client_local(const char *path) +{ + struct sockaddr_un sa; + char *ptr; + int stype; + + if (snmp_client.chost == NULL) { + if ((snmp_client.chost = malloc(1 + sizeof(DEFAULT_LOCAL))) + == NULL) { + seterr(&snmp_client, "%s", strerror(errno)); + return (-1); + } + strcpy(snmp_client.chost, DEFAULT_LOCAL); + } + if (path != NULL) { + if ((ptr = malloc(1 + strlen(path))) == NULL) { + seterr(&snmp_client, "%s", strerror(errno)); + return (-1); + } + free(snmp_client.chost); + snmp_client.chost = ptr; + strcpy(snmp_client.chost, path); + } + + if (snmp_client.trans == SNMP_TRANS_LOC_DGRAM) + stype = SOCK_DGRAM; + else + stype = SOCK_STREAM; + + if ((snmp_client.fd = socket(PF_LOCAL, stype, 0)) == -1) { + seterr(&snmp_client, "%s", strerror(errno)); + return (-1); + } + + snprintf(snmp_client.local_path, sizeof(snmp_client.local_path), + "%s", SNMP_LOCAL_PATH); + + if (mktemp(snmp_client.local_path) == NULL) { + seterr(&snmp_client, "%s", strerror(errno)); + (void)close(snmp_client.fd); + snmp_client.fd = -1; + return (-1); + } + + sa.sun_family = AF_LOCAL; + sa.sun_len = sizeof(sa); + strcpy(sa.sun_path, snmp_client.local_path); + + if (bind(snmp_client.fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { + seterr(&snmp_client, "%s", strerror(errno)); + (void)close(snmp_client.fd); + snmp_client.fd = -1; + (void)remove(snmp_client.local_path); + return (-1); + } + atexit(remove_local); + + sa.sun_family = AF_LOCAL; + sa.sun_len = offsetof(struct sockaddr_un, sun_path) + + strlen(snmp_client.chost); + strncpy(sa.sun_path, snmp_client.chost, sizeof(sa.sun_path) - 1); + sa.sun_path[sizeof(sa.sun_path) - 1] = '\0'; + + if (connect(snmp_client.fd, (struct sockaddr *)&sa, sa.sun_len) == -1) { + seterr(&snmp_client, "%s", strerror(errno)); + (void)close(snmp_client.fd); + snmp_client.fd = -1; + (void)remove(snmp_client.local_path); + return (-1); + } + return (0); +} + +/* + * SNMP_OPEN + */ +int +snmp_open(const char *host, const char *port, const char *readcomm, + const char *writecomm) +{ + struct timeval tout; + + /* still open ? */ + if (snmp_client.fd != -1) { + errno = EBUSY; + seterr(&snmp_client, "%s", strerror(errno)); + return (-1); + } + + /* copy community strings */ + if (readcomm != NULL) + strlcpy(snmp_client.read_community, readcomm, + sizeof(snmp_client.read_community)); + if (writecomm != NULL) + strlcpy(snmp_client.write_community, writecomm, + sizeof(snmp_client.write_community)); + + switch (snmp_client.trans) { + + case SNMP_TRANS_UDP: + if (open_client_udp(host, port) != 0) + return (-1); + break; + + case SNMP_TRANS_LOC_DGRAM: + case SNMP_TRANS_LOC_STREAM: + if (open_client_local(host) != 0) + return (-1); + break; + + default: + seterr(&snmp_client, "bad transport mapping"); + return (-1); + } + tout.tv_sec = 0; + tout.tv_usec = 0; + if (setsockopt(snmp_client.fd, SOL_SOCKET, SO_SNDTIMEO, + &tout, sizeof(struct timeval)) == -1) { + seterr(&snmp_client, "%s", strerror(errno)); + (void)close(snmp_client.fd); + snmp_client.fd = -1; + if (snmp_client.local_path[0] != '\0') + (void)remove(snmp_client.local_path); + return (-1); + } + + /* initialize list */ + LIST_INIT(&sent_pdus); + + return (0); +} + + +/* + * SNMP_CLOSE + * + * closes connection to snmp server + * - function cannot fail + * - clears connection + * - clears list of sent pdus + * + * input: + * void + * return: + * void + */ +void +snmp_close(void) +{ + struct sent_pdu *p1; + + if (snmp_client.fd != -1) { + (void)close(snmp_client.fd); + snmp_client.fd = -1; + if (snmp_client.local_path[0] != '\0') + (void)remove(snmp_client.local_path); + } + while(!LIST_EMPTY(&sent_pdus)){ + p1 = LIST_FIRST(&sent_pdus); + if (p1->timeout_id != NULL) + snmp_client.timeout_stop(p1->timeout_id); + LIST_REMOVE(p1, entries); + free(p1); + } + free(snmp_client.chost); + free(snmp_client.cport); +} + +/* + * initialize a snmp_pdu structure + */ +void +snmp_pdu_create(struct snmp_pdu *pdu, u_int op) +{ + memset(pdu, 0, sizeof(struct snmp_pdu)); + + if (op == SNMP_PDU_SET) + strlcpy(pdu->community, snmp_client.write_community, + sizeof(pdu->community)); + else + strlcpy(pdu->community, snmp_client.read_community, + sizeof(pdu->community)); + + pdu->type = op; + pdu->version = snmp_client.version; + pdu->error_status = 0; + pdu->error_index = 0; + pdu->nbindings = 0; + + if (snmp_client.version != SNMP_V3) + return; + + pdu->identifier = ++snmp_client.identifier; + pdu->engine.max_msg_size = snmp_client.engine.max_msg_size; + pdu->flags = 0; + pdu->security_model = snmp_client.security_model; + + if (snmp_client.security_model == SNMP_SECMODEL_USM) { + memcpy(&pdu->engine, &snmp_client.engine, sizeof(pdu->engine)); + memcpy(&pdu->user, &snmp_client.user, sizeof(pdu->user)); + snmp_pdu_init_secparams(pdu); + } else + seterr(&snmp_client, "unknown security model"); + + if (snmp_client.clen > 0) { + memcpy(pdu->context_engine, snmp_client.cengine, + snmp_client.clen); + pdu->context_engine_len = snmp_client.clen; + } else { + memcpy(pdu->context_engine, snmp_client.engine.engine_id, + snmp_client.engine.engine_len); + pdu->context_engine_len = snmp_client.engine.engine_len; + } + + strlcpy(pdu->context_name, snmp_client.cname, + sizeof(pdu->context_name)); +} + +/* add pairs of (struct asn_oid, enum snmp_syntax) to an existing pdu */ +/* added 10/04/02 by kek: check for MAX_BINDINGS */ +int +snmp_add_binding(struct snmp_v1_pdu *pdu, ...) +{ + va_list ap; + const struct asn_oid *oid; + u_int ret; + + va_start(ap, pdu); + + ret = pdu->nbindings; + while ((oid = va_arg(ap, const struct asn_oid *)) != NULL) { + if (pdu->nbindings >= SNMP_MAX_BINDINGS){ + va_end(ap); + return (-1); + } + pdu->bindings[pdu->nbindings].var = *oid; + pdu->bindings[pdu->nbindings].syntax = + va_arg(ap, enum snmp_syntax); + pdu->nbindings++; + } + va_end(ap); + return (ret); +} + + +static int32_t +snmp_next_reqid(struct snmp_client * c) +{ + int32_t i; + + i = c->next_reqid; + if (c->next_reqid >= c->max_reqid) + c->next_reqid = c->min_reqid; + else + c->next_reqid++; + return (i); +} + +/* + * Send request and return request id. + */ +static int32_t +snmp_send_packet(struct snmp_pdu * pdu) +{ + u_char *buf; + struct asn_buf b; + ssize_t ret; + + if ((buf = calloc(1, snmp_client.txbuflen)) == NULL) { + seterr(&snmp_client, "%s", strerror(errno)); + return (-1); + } + + pdu->request_id = snmp_next_reqid(&snmp_client); + + b.asn_ptr = buf; + b.asn_len = snmp_client.txbuflen; + if (snmp_pdu_encode(pdu, &b)) { + seterr(&snmp_client, "%s", strerror(errno)); + free(buf); + return (-1); + } + + if (snmp_client.dump_pdus) + snmp_pdu_dump(pdu); + + if ((ret = send(snmp_client.fd, buf, b.asn_ptr - buf, 0)) == -1) { + seterr(&snmp_client, "%s", strerror(errno)); + free(buf); + return (-1); + } + free(buf); + + return (pdu->request_id); +} + +/* + * to be called when a snmp request timed out + */ +static void +snmp_timeout(void * listentry_ptr) +{ + struct sent_pdu *listentry = listentry_ptr; + +#if 0 + warnx("snmp request %i timed out, attempt (%i/%i)", + listentry->reqid, listentry->retrycount, snmp_client.retries); +#endif + + listentry->retrycount++; + if (listentry->retrycount > snmp_client.retries) { + /* there is no answer at all */ + LIST_REMOVE(listentry, entries); + listentry->callback(listentry->pdu, NULL, listentry->arg); + free(listentry); + } else { + /* try again */ + /* new request with new request ID */ + listentry->reqid = snmp_send_packet(listentry->pdu); + listentry->timeout_id = + snmp_client.timeout_start(&snmp_client.timeout, + snmp_timeout, listentry); + } +} + +int32_t +snmp_pdu_send(struct snmp_pdu *pdu, snmp_send_cb_f func, void *arg) +{ + struct sent_pdu *listentry; + int32_t id; + + if ((listentry = malloc(sizeof(struct sent_pdu))) == NULL) { + seterr(&snmp_client, "%s", strerror(errno)); + return (-1); + } + + /* here we really send */ + if ((id = snmp_send_packet(pdu)) == -1) { + free(listentry); + return (-1); + } + + /* add entry to list of sent PDUs */ + listentry->pdu = pdu; + if (gettimeofday(&listentry->time, NULL) == -1) + warn("gettimeofday() failed"); + + listentry->reqid = pdu->request_id; + listentry->callback = func; + listentry->arg = arg; + listentry->retrycount=1; + listentry->timeout_id = + snmp_client.timeout_start(&snmp_client.timeout, snmp_timeout, + listentry); + + LIST_INSERT_HEAD(&sent_pdus, listentry, entries); + + return (id); +} + +/* + * Receive an SNMP packet. + * + * tv controls how we wait for a packet: if tv is a NULL pointer, + * the receive blocks forever, if tv points to a structure with all + * members 0 the socket is polled, in all other cases tv specifies the + * maximum time to wait for a packet. + * + * Return: + * -1 on errors + * 0 on timeout + * +1 if packet received + */ +static int +snmp_receive_packet(struct snmp_pdu *pdu, struct timeval *tv) +{ + int dopoll, setpoll; + int flags; + int saved_errno; + u_char *buf; + int ret; + struct asn_buf abuf; + int32_t ip; +#ifdef bsdi + int optlen; +#else + socklen_t optlen; +#endif + + if ((buf = calloc(1, snmp_client.rxbuflen)) == NULL) { + seterr(&snmp_client, "%s", strerror(errno)); + return (-1); + } + dopoll = setpoll = 0; + flags = 0; + if (tv != NULL) { + /* poll or timeout */ + if (tv->tv_sec != 0 || tv->tv_usec != 0) { + /* wait with timeout */ + if (setsockopt(snmp_client.fd, SOL_SOCKET, SO_RCVTIMEO, + tv, sizeof(*tv)) == -1) { + seterr(&snmp_client, "setsockopt: %s", + strerror(errno)); + free(buf); + return (-1); + } + optlen = sizeof(*tv); + if (getsockopt(snmp_client.fd, SOL_SOCKET, SO_RCVTIMEO, + tv, &optlen) == -1) { + seterr(&snmp_client, "getsockopt: %s", + strerror(errno)); + free(buf); + return (-1); + } + /* at this point tv_sec and tv_usec may appear + * as 0. This happens for timeouts lesser than + * the clock granularity. The kernel rounds these to + * 0 and this would result in a blocking receive. + * Instead of an else we check tv_sec and tv_usec + * again below and if this rounding happens, + * switch to a polling receive. */ + } + if (tv->tv_sec == 0 && tv->tv_usec == 0) { + /* poll */ + dopoll = 1; + if ((flags = fcntl(snmp_client.fd, F_GETFL, 0)) == -1) { + seterr(&snmp_client, "fcntl: %s", + strerror(errno)); + free(buf); + return (-1); + } + if (!(flags & O_NONBLOCK)) { + setpoll = 1; + flags |= O_NONBLOCK; + if (fcntl(snmp_client.fd, F_SETFL, flags) == -1) { + seterr(&snmp_client, "fcntl: %s", + strerror(errno)); + free(buf); + return (-1); + } + } + } + } + ret = recv(snmp_client.fd, buf, snmp_client.rxbuflen, 0); + saved_errno = errno; + if (tv != NULL) { + if (dopoll) { + if (setpoll) { + flags &= ~O_NONBLOCK; + (void)fcntl(snmp_client.fd, F_SETFL, flags); + } + } else { + tv->tv_sec = 0; + tv->tv_usec = 0; + (void)setsockopt(snmp_client.fd, SOL_SOCKET, SO_RCVTIMEO, + tv, sizeof(*tv)); + } + } + if (ret == -1) { + free(buf); + if (errno == EAGAIN || errno == EWOULDBLOCK) + return (0); + seterr(&snmp_client, "recv: %s", strerror(saved_errno)); + return (-1); + } + if (ret == 0) { + /* this happens when we have a streaming socket and the + * remote side has closed it */ + free(buf); + seterr(&snmp_client, "recv: socket closed by peer"); + errno = EPIPE; + return (-1); + } + + abuf.asn_ptr = buf; + abuf.asn_len = ret; + + memset(pdu, 0, sizeof(*pdu)); + if (snmp_client.security_model == SNMP_SECMODEL_USM) { + memcpy(&pdu->engine, &snmp_client.engine, sizeof(pdu->engine)); + memcpy(&pdu->user, &snmp_client.user, sizeof(pdu->user)); + snmp_pdu_init_secparams(pdu); + } + + if (SNMP_CODE_OK != (ret = snmp_pdu_decode(&abuf, pdu, &ip))) { + seterr(&snmp_client, "snmp_decode_pdu: failed %d", ret); + free(buf); + return (-1); + } + + free(buf); + if (snmp_client.dump_pdus) + snmp_pdu_dump(pdu); + + snmp_client.engine.engine_time = pdu->engine.engine_time; + snmp_client.engine.engine_boots = pdu->engine.engine_boots; + + return (+1); +} + +static int +snmp_deliver_packet(struct snmp_pdu * resp) +{ + struct sent_pdu *listentry; + + if (resp->type != SNMP_PDU_RESPONSE) { + warn("ignoring snmp pdu %u", resp->type); + return (-1); + } + + LIST_FOREACH(listentry, &sent_pdus, entries) + if (listentry->reqid == resp->request_id) + break; + if (listentry == NULL) + return (-1); + + LIST_REMOVE(listentry, entries); + listentry->callback(listentry->pdu, resp, listentry->arg); + + snmp_client.timeout_stop(listentry->timeout_id); + + free(listentry); + return (0); +} + +int +snmp_receive(int blocking) +{ + int ret; + + struct timeval tv; + struct snmp_pdu * resp; + + memset(&tv, 0, sizeof(tv)); + + resp = malloc(sizeof(struct snmp_pdu)); + if (resp == NULL) { + seterr(&snmp_client, "no memory for returning PDU"); + return (-1) ; + } + + if ((ret = snmp_receive_packet(resp, blocking ? NULL : &tv)) <= 0) { + free(resp); + return (ret); + } + ret = snmp_deliver_packet(resp); + snmp_pdu_free(resp); + free(resp); + return (ret); +} + + +/* + * Check a GETNEXT response. Here we have three possible outcomes: -1 an + * unexpected error happened. +1 response is ok and is within the table 0 + * response is ok, but is behind the table or error is NOSUCHNAME. The req + * should point to a template PDU which contains the base OIDs and the + * syntaxes. This is really only useful to sweep non-sparse tables. + */ +static int +ok_getnext(const struct snmp_pdu * req, const struct snmp_pdu * resp) +{ + u_int i; + + if (resp->version != req->version) { + warnx("SNMP GETNEXT: response has wrong version"); + return (-1); + } + + if (resp->error_status == SNMP_ERR_NOSUCHNAME) + return (0); + + if (resp->error_status != SNMP_ERR_NOERROR) { + warnx("SNMP GETNEXT: error %d", resp->error_status); + return (-1); + } + if (resp->nbindings != req->nbindings) { + warnx("SNMP GETNEXT: bad number of bindings in response"); + return (-1); + } + for (i = 0; i < req->nbindings; i++) { + if (!asn_is_suboid(&req->bindings[i].var, + &resp->bindings[i].var)) { + if (i != 0) + warnx("SNMP GETNEXT: inconsistent table " + "response"); + return (0); + } + if (resp->version != SNMP_V1 && + resp->bindings[i].syntax == SNMP_SYNTAX_ENDOFMIBVIEW) + return (0); + + if (resp->bindings[i].syntax != req->bindings[i].syntax) { + warnx("SNMP GETNEXT: bad syntax in response"); + return (0); + } + } + return (1); +} + +/* + * Check a GET response. Here we have three possible outcomes: -1 an + * unexpected error happened. +1 response is ok. 0 NOSUCHNAME The req should + * point to a template PDU which contains the OIDs and the syntaxes. This + * is only useful for SNMPv1 or single object GETS. + */ +static int +ok_get(const struct snmp_pdu * req, const struct snmp_pdu * resp) +{ + u_int i; + + if (resp->version != req->version) { + warnx("SNMP GET: response has wrong version"); + return (-1); + } + + if (resp->error_status == SNMP_ERR_NOSUCHNAME) + return (0); + + if (resp->error_status != SNMP_ERR_NOERROR) { + warnx("SNMP GET: error %d", resp->error_status); + return (-1); + } + + if (resp->nbindings != req->nbindings) { + warnx("SNMP GET: bad number of bindings in response"); + return (-1); + } + for (i = 0; i < req->nbindings; i++) { + if (asn_compare_oid(&req->bindings[i].var, + &resp->bindings[i].var) != 0) { + warnx("SNMP GET: bad OID in response"); + return (-1); + } + if (snmp_client.version != SNMP_V1 && + (resp->bindings[i].syntax == SNMP_SYNTAX_NOSUCHOBJECT || + resp->bindings[i].syntax == SNMP_SYNTAX_NOSUCHINSTANCE)) + return (0); + if (resp->bindings[i].syntax != req->bindings[i].syntax) { + warnx("SNMP GET: bad syntax in response"); + return (-1); + } + } + return (1); +} + +/* + * Check the response to a SET PDU. We check: - the error status must be 0 - + * the number of bindings must be equal in response and request - the + * syntaxes must be the same in response and request - the OIDs must be the + * same in response and request + */ +static int +ok_set(const struct snmp_pdu * req, const struct snmp_pdu * resp) +{ + u_int i; + + if (resp->version != req->version) { + warnx("SNMP SET: response has wrong version"); + return (-1); + } + + if (resp->error_status == SNMP_ERR_NOSUCHNAME) { + warnx("SNMP SET: error %d", resp->error_status); + return (0); + } + if (resp->error_status != SNMP_ERR_NOERROR) { + warnx("SNMP SET: error %d", resp->error_status); + return (-1); + } + + if (resp->nbindings != req->nbindings) { + warnx("SNMP SET: bad number of bindings in response"); + return (-1); + } + for (i = 0; i < req->nbindings; i++) { + if (asn_compare_oid(&req->bindings[i].var, + &resp->bindings[i].var) != 0) { + warnx("SNMP SET: wrong OID in response to SET"); + return (-1); + } + if (resp->bindings[i].syntax != req->bindings[i].syntax) { + warnx("SNMP SET: bad syntax in response"); + return (-1); + } + } + return (1); +} + +/* + * Simple checks for response PDUs against request PDUs. Return values: 1=ok, + * 0=nosuchname or similar, -1=failure, -2=no response at all + */ +int +snmp_pdu_check(const struct snmp_pdu *req, + const struct snmp_pdu *resp) +{ + if (resp == NULL) + return (-2); + + switch (req->type) { + + case SNMP_PDU_GET: + return (ok_get(req, resp)); + + case SNMP_PDU_SET: + return (ok_set(req, resp)); + + case SNMP_PDU_GETNEXT: + return (ok_getnext(req, resp)); + + } + errx(1, "%s: bad pdu type %i", __func__, req->type); +} + +int +snmp_dialog(struct snmp_v1_pdu *req, struct snmp_v1_pdu *resp) +{ + struct timeval tv = snmp_client.timeout; + struct timeval end; + struct snmp_pdu pdu; + int ret; + int32_t reqid; + u_int i; + + /* + * Make a copy of the request and replace the syntaxes by NULL + * if this is a GET,GETNEXT or GETBULK. + */ + pdu = *req; + if (pdu.type == SNMP_PDU_GET || pdu.type == SNMP_PDU_GETNEXT || + pdu.type == SNMP_PDU_GETBULK) { + for (i = 0; i < pdu.nbindings; i++) + pdu.bindings[i].syntax = SNMP_SYNTAX_NULL; + } + + for (i = 0; i <= snmp_client.retries; i++) { + (void)gettimeofday(&end, NULL); + timeradd(&end, &snmp_client.timeout, &end); + if ((reqid = snmp_send_packet(&pdu)) == -1) + return (-1); + for (;;) { + (void)gettimeofday(&tv, NULL); + if (timercmp(&end, &tv, <=)) + break; + timersub(&end, &tv, &tv); + if ((ret = snmp_receive_packet(resp, &tv)) == 0) + /* timeout */ + break; + + if (ret > 0) { + if (reqid == resp->request_id) + return (0); + /* not for us */ + (void)snmp_deliver_packet(resp); + } + if (ret < 0 && errno == EPIPE) + /* stream closed */ + return (-1); + } + } + errno = ETIMEDOUT; + seterr(&snmp_client, "retry count exceeded"); + return (-1); +} + +int +snmp_discover_engine(char *passwd) +{ + char cname[SNMP_ADM_STR32_SIZ]; + enum snmp_authentication cap; + enum snmp_privacy cpp; + struct snmp_pdu req, resp; + + if (snmp_client.version != SNMP_V3) + seterr(&snmp_client, "wrong version"); + + strlcpy(cname, snmp_client.user.sec_name, sizeof(cname)); + cap = snmp_client.user.auth_proto; + cpp = snmp_client.user.priv_proto; + + snmp_client.engine.engine_len = 0; + snmp_client.engine.engine_boots = 0; + snmp_client.engine.engine_time = 0; + snmp_client.user.auth_proto = SNMP_AUTH_NOAUTH; + snmp_client.user.priv_proto = SNMP_PRIV_NOPRIV; + memset(snmp_client.user.sec_name, 0, sizeof(snmp_client.user.sec_name)); + + snmp_pdu_create(&req, SNMP_PDU_GET); + + if (snmp_dialog(&req, &resp) == -1) + return (-1); + + if (resp.version != req.version) { + seterr(&snmp_client, "wrong version"); + return (-1); + } + + if (resp.error_status != SNMP_ERR_NOERROR) { + seterr(&snmp_client, "Error %d in responce", resp.error_status); + return (-1); + } + + snmp_client.engine.engine_len = resp.engine.engine_len; + snmp_client.engine.max_msg_size = resp.engine.max_msg_size; + memcpy(snmp_client.engine.engine_id, resp.engine.engine_id, + resp.engine.engine_len); + + strlcpy(snmp_client.user.sec_name, cname, + sizeof(snmp_client.user.sec_name)); + snmp_client.user.auth_proto = cap; + snmp_client.user.priv_proto = cpp; + + if (snmp_client.user.auth_proto == SNMP_AUTH_NOAUTH) + return (0); + + if (passwd == NULL || + snmp_passwd_to_keys(&snmp_client.user, passwd) != SNMP_CODE_OK || + snmp_get_local_keys(&snmp_client.user, snmp_client.engine.engine_id, + snmp_client.engine.engine_len) != SNMP_CODE_OK) + return (-1); + + if (resp.engine.engine_boots != 0) + snmp_client.engine.engine_boots = resp.engine.engine_boots; + + if (resp.engine.engine_time != 0) { + snmp_client.engine.engine_time = resp.engine.engine_time; + return (0); + } + + snmp_pdu_free(&req); + + snmp_pdu_create(&req, SNMP_PDU_GET); + req.engine.engine_boots = 0; + req.engine.engine_time = 0; + + if (snmp_dialog(&req, &resp) == -1) + return (-1); + + if (resp.version != req.version) { + seterr(&snmp_client, "wrong version"); + return (-1); + } + + if (resp.error_status != SNMP_ERR_NOERROR) { + seterr(&snmp_client, "Error %d in responce", resp.error_status); + return (-1); + } + + snmp_client.engine.engine_boots = resp.engine.engine_boots; + snmp_client.engine.engine_time = resp.engine.engine_time; + + snmp_pdu_free(&req); + snmp_pdu_free(&resp); + + return (0); +} + +int +snmp_client_set_host(struct snmp_client *cl, const char *h) +{ + char *np; + + if (h == NULL) { + if (cl->chost != NULL) + free(cl->chost); + cl->chost = NULL; + } else { + if ((np = malloc(strlen(h) + 1)) == NULL) + return (-1); + strcpy(np, h); + if (cl->chost != NULL) + free(cl->chost); + cl->chost = np; + } + return (0); +} + +int +snmp_client_set_port(struct snmp_client *cl, const char *p) +{ + char *np; + + if (p == NULL) { + if (cl->cport != NULL) + free(cl->cport); + cl->cport = NULL; + } else { + if ((np = malloc(strlen(p) + 1)) == NULL) + return (-1); + strcpy(np, p); + if (cl->cport != NULL) + free(cl->cport); + cl->cport = np; + } + return (0); +} + +/* + * parse a server specification + * + * [trans::][community@][server][:port] + */ +int +snmp_parse_server(struct snmp_client *sc, const char *str) +{ + const char *p, *s = str; + + /* look for a double colon */ + for (p = s; *p != '\0'; p++) { + if (*p == '\\' && p[1] != '\0') { + p++; + continue; + } + if (*p == ':' && p[1] == ':') + break; + } + if (*p != '\0') { + if (p > s) { + if (p - s == 3 && strncmp(s, "udp", 3) == 0) + sc->trans = SNMP_TRANS_UDP; + else if (p - s == 6 && strncmp(s, "stream", 6) == 0) + sc->trans = SNMP_TRANS_LOC_STREAM; + else if (p - s == 5 && strncmp(s, "dgram", 5) == 0) + sc->trans = SNMP_TRANS_LOC_DGRAM; + else { + seterr(sc, "unknown SNMP transport '%.*s'", + (int)(p - s), s); + return (-1); + } + } + s = p + 2; + } + + /* look for a @ */ + for (p = s; *p != '\0'; p++) { + if (*p == '\\' && p[1] != '\0') { + p++; + continue; + } + if (*p == '@') + break; + } + + if (*p != '\0') { + if (p - s > SNMP_COMMUNITY_MAXLEN) { + seterr(sc, "community string too long"); + return (-1); + } + strncpy(sc->read_community, s, p - s); + sc->read_community[p - s] = '\0'; + strncpy(sc->write_community, s, p - s); + sc->write_community[p - s] = '\0'; + s = p + 1; + } + + /* look for a colon */ + for (p = s; *p != '\0'; p++) { + if (*p == '\\' && p[1] != '\0') { + p++; + continue; + } + if (*p == ':') + break; + } + + if (*p == ':') { + if (p > s) { + /* host:port */ + free(sc->chost); + if ((sc->chost = malloc(p - s + 1)) == NULL) { + seterr(sc, "%s", strerror(errno)); + return (-1); + } + strncpy(sc->chost, s, p - s); + sc->chost[p - s] = '\0'; + } + /* port */ + free(sc->cport); + if ((sc->cport = strdup(p + 1)) == NULL) { + seterr(sc, "%s", strerror(errno)); + return (-1); + } + + } else if (p > s) { + /* host */ + free(sc->chost); + if ((sc->chost = strdup(s)) == NULL) { + seterr(sc, "%s", strerror(errno)); + return (-1); + } + } + return (0); +} Property changes on: vendor/bsnmp/1.13/lib/snmpclient.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/snmpclient.h =================================================================== --- vendor/bsnmp/1.13/lib/snmpclient.h (nonexistent) +++ vendor/bsnmp/1.13/lib/snmpclient.h (revision 336778) @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * Kendy Kutzner + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/lib/snmpclient.h,v 1.19 2005/05/23 11:10:14 brandt_h Exp $ + */ +#ifndef _BSNMP_SNMPCLIENT_H +#define _BSNMP_SNMPCLIENT_H + +#include +#include +#include +#include +#include + + +#define SNMP_STRERROR_LEN 200 + +#define SNMP_LOCAL_PATH "/tmp/snmpXXXXXXXXXXXXXX" + +/* + * transport methods + */ +#define SNMP_TRANS_UDP 0 +#define SNMP_TRANS_LOC_DGRAM 1 +#define SNMP_TRANS_LOC_STREAM 2 + +/* type of callback function for responses + * this callback function is responsible for free() any memory associated with + * any of the PDUs. Therefor it may call snmp_pdu_free() */ +typedef void (*snmp_send_cb_f)(struct snmp_pdu *, struct snmp_pdu *, void *); + +/* type of callback function for timeouts */ +typedef void (*snmp_timeout_cb_f)(void * ); + +/* timeout start function */ +typedef void *(*snmp_timeout_start_f)(struct timeval *timeout, + snmp_timeout_cb_f callback, void *); + +/* timeout stop function */ +typedef void (*snmp_timeout_stop_f)(void *timeout_id); + +/* + * Client context. + */ +struct snmp_client { + enum snmp_version version; + int trans; /* which transport to use */ + + /* these two are read-only for the application */ + char *cport; /* port number as string */ + char *chost; /* host name or IP address as string */ + + char read_community[SNMP_COMMUNITY_MAXLEN + 1]; + char write_community[SNMP_COMMUNITY_MAXLEN + 1]; + + /* SNMPv3 specific fields */ + int32_t identifier; + int32_t security_model; + struct snmp_engine engine; + struct snmp_user user; + + /* SNMPv3 Access control - VACM*/ + uint32_t clen; + uint8_t cengine[SNMP_ENGINE_ID_SIZ]; + char cname[SNMP_CONTEXT_NAME_SIZ]; + + struct timeval timeout; + u_int retries; + + int dump_pdus; + + size_t txbuflen; + size_t rxbuflen; + + int fd; + + int32_t next_reqid; + int32_t max_reqid; + int32_t min_reqid; + + char error[SNMP_STRERROR_LEN]; + + snmp_timeout_start_f timeout_start; + snmp_timeout_stop_f timeout_stop; + + char local_path[sizeof(SNMP_LOCAL_PATH)]; +}; + +/* the global context */ +extern struct snmp_client snmp_client; + +/* initizialies a snmp_client structure */ +void snmp_client_init(struct snmp_client *); + +/* initialize fields */ +int snmp_client_set_host(struct snmp_client *, const char *); +int snmp_client_set_port(struct snmp_client *, const char *); + +/* open connection to snmp server (hostname or portname can be NULL) */ +int snmp_open(const char *_hostname, const char *_portname, + const char *_read_community, const char *_write_community); + +/* close connection */ +void snmp_close(void); + +/* initialize a snmp_pdu structure */ +void snmp_pdu_create(struct snmp_pdu *, u_int _op); + +/* add pairs of (struct asn_oid *, enum snmp_syntax) to an existing pdu */ +int snmp_add_binding(struct snmp_pdu *, ...); + +/* check wheater the answer is valid or not */ +int snmp_pdu_check(const struct snmp_pdu *_req, const struct snmp_pdu *_resp); + +int32_t snmp_pdu_send(struct snmp_pdu *_pdu, snmp_send_cb_f _func, void *_arg); + +/* append an index to an oid */ +int snmp_oid_append(struct asn_oid *_oid, const char *_fmt, ...); + +/* receive a packet */ +int snmp_receive(int _blocking); + +/* + * This structure is used to describe an SNMP table that is to be fetched. + * The C-structure that is produced by the fetch function must start with + * a TAILQ_ENTRY and an u_int64_t. + */ +struct snmp_table { + /* base OID of the table */ + struct asn_oid table; + /* type OID of the LastChange variable for the table if any */ + struct asn_oid last_change; + /* maximum number of iterations if table has changed */ + u_int max_iter; + /* size of the C-structure */ + size_t entry_size; + /* number of index fields */ + u_int index_size; + /* bit mask of required fields */ + uint64_t req_mask; + + /* indexes and columns to fetch. Ended by a NULL syntax entry */ + struct snmp_table_entry { + /* the column sub-oid, ignored for index fields */ + asn_subid_t subid; + /* the syntax of the column or index */ + enum snmp_syntax syntax; + /* offset of the field into the C-structure. For octet strings + * this points to an u_char * followed by a size_t */ + off_t offset; +#if defined(__GNUC__) && __GNUC__ < 3 + } entries[0]; +#else + } entries[]; +#endif +}; + +/* callback type for table fetch */ +typedef void (*snmp_table_cb_f)(void *_list, void *_arg, int _res); + +/* fetch a table. The argument points to a TAILQ_HEAD */ +int snmp_table_fetch(const struct snmp_table *descr, void *); +int snmp_table_fetch_async(const struct snmp_table *, void *, + snmp_table_cb_f, void *); + +/* send a request and wait for the response */ +int snmp_dialog(struct snmp_pdu *_req, struct snmp_pdu *_resp); + +/* discover an authorative snmpEngineId */ +int snmp_discover_engine(char *); + +/* parse a server specification */ +int snmp_parse_server(struct snmp_client *, const char *); + +#endif /* _BSNMP_SNMPCLIENT_H */ Property changes on: vendor/bsnmp/1.13/lib/snmpclient.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/snmpcrypto.c =================================================================== --- vendor/bsnmp/1.13/lib/snmpcrypto.c (nonexistent) +++ vendor/bsnmp/1.13/lib/snmpcrypto.c (revision 336778) @@ -0,0 +1,402 @@ +/*- + * Copyright (c) 2010 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Shteryana Sotirova Shopova under + * sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/contrib/bsnmp/lib/snmpcrypto.c 310648 2016-12-27 23:32:54Z ngie $ + */ +#include +#include +#include +#include +#include +#include +#ifdef HAVE_STDINT_H +#include +#elif defined(HAVE_INTTYPES_H) +#include +#endif +#include +#include +#include +#include + +#ifdef HAVE_LIBCRYPTO +#include +#endif + +#include "asn1.h" +#include "snmp.h" +#include "snmppriv.h" + +#define SNMP_PRIV_AES_IV_SIZ 16 +#define SNMP_EXTENDED_KEY_SIZ 64 +#define SNMP_AUTH_KEY_LOOPCNT 1048576 +#define SNMP_AUTH_BUF_SIZE 72 + +static const uint8_t ipad = 0x36; +static const uint8_t opad = 0x5c; + +#ifdef HAVE_LIBCRYPTO + +static int32_t +snmp_digest_init(const struct snmp_user *user, EVP_MD_CTX *ctx, + const EVP_MD **dtype, uint32_t *keylen) +{ + if (user->auth_proto == SNMP_AUTH_HMAC_MD5) { + *dtype = EVP_md5(); + *keylen = SNMP_AUTH_HMACMD5_KEY_SIZ; + } else if (user->auth_proto == SNMP_AUTH_HMAC_SHA) { + *dtype = EVP_sha1(); + *keylen = SNMP_AUTH_HMACSHA_KEY_SIZ; + } else if (user->auth_proto == SNMP_AUTH_NOAUTH) + return (0); + else { + snmp_error("unknown authentication option - %d", + user->auth_proto); + return (-1); + } + + if (EVP_DigestInit(ctx, *dtype) != 1) + return (-1); + + return (1); +} + +enum snmp_code +snmp_pdu_calc_digest(const struct snmp_pdu *pdu, uint8_t *digest) +{ + uint8_t md[EVP_MAX_MD_SIZE], extkey[SNMP_EXTENDED_KEY_SIZ]; + uint8_t key1[SNMP_EXTENDED_KEY_SIZ], key2[SNMP_EXTENDED_KEY_SIZ]; + uint32_t i, keylen, olen; + int32_t err; + const EVP_MD *dtype; + EVP_MD_CTX ctx; + + err = snmp_digest_init(&pdu->user, &ctx, &dtype, &keylen); + if (err < 0) + return (SNMP_CODE_BADDIGEST); + else if (err == 0) + return (SNMP_CODE_OK); + + memset(pdu->digest_ptr, 0, sizeof(pdu->msg_digest)); + memcpy(extkey, pdu->user.auth_key, keylen); + memset(extkey + keylen, 0, sizeof(extkey) - keylen); + + for (i = 0; i < SNMP_EXTENDED_KEY_SIZ; i++) { + key1[i] = extkey[i] ^ ipad; + key2[i] = extkey[i] ^ opad; + } + + if (EVP_DigestUpdate(&ctx, key1, SNMP_EXTENDED_KEY_SIZ) != 1 || + EVP_DigestUpdate(&ctx, pdu->outer_ptr, pdu->outer_len) != 1 || + EVP_DigestFinal(&ctx, md, &olen) != 1) + goto failed; + + if (EVP_DigestInit(&ctx, dtype) != 1 || + EVP_DigestUpdate(&ctx, key2, SNMP_EXTENDED_KEY_SIZ) != 1 || + EVP_DigestUpdate(&ctx, md, olen) != 1 || + EVP_DigestFinal(&ctx, md, &olen) != 1) + goto failed; + + if (olen < SNMP_USM_AUTH_SIZE) { + snmp_error("bad digest size - %d", olen); + EVP_MD_CTX_cleanup(&ctx); + return (SNMP_CODE_BADDIGEST); + } + + memcpy(digest, md, SNMP_USM_AUTH_SIZE); + EVP_MD_CTX_cleanup(&ctx); + return (SNMP_CODE_OK); + +failed: + EVP_MD_CTX_cleanup(&ctx); + return (SNMP_CODE_BADDIGEST); +} + +static int32_t +snmp_pdu_cipher_init(const struct snmp_pdu *pdu, int32_t len, + const EVP_CIPHER **ctype, uint8_t *piv) +{ + int i; + uint32_t netint; + + if (pdu->user.priv_proto == SNMP_PRIV_DES) { + if (len % 8 != 0) + return (-1); + *ctype = EVP_des_cbc(); + memcpy(piv, pdu->msg_salt, sizeof(pdu->msg_salt)); + for (i = 0; i < 8; i++) + piv[i] = piv[i] ^ pdu->user.priv_key[8 + i]; + } else if (pdu->user.priv_proto == SNMP_PRIV_AES) { + *ctype = EVP_aes_128_cfb128(); + netint = htonl(pdu->engine.engine_boots); + memcpy(piv, &netint, sizeof(netint)); + piv += sizeof(netint); + netint = htonl(pdu->engine.engine_time); + memcpy(piv, &netint, sizeof(netint)); + piv += sizeof(netint); + memcpy(piv, pdu->msg_salt, sizeof(pdu->msg_salt)); + } else if (pdu->user.priv_proto == SNMP_PRIV_NOPRIV) + return (0); + else { + snmp_error("unknown privacy option - %d", pdu->user.priv_proto); + return (-1); + } + + return (1); +} + +enum snmp_code +snmp_pdu_encrypt(const struct snmp_pdu *pdu) +{ + int32_t err, olen; + uint8_t iv[SNMP_PRIV_AES_IV_SIZ]; + const EVP_CIPHER *ctype; + EVP_CIPHER_CTX ctx; + + err = snmp_pdu_cipher_init(pdu, pdu->scoped_len, &ctype, iv); + if (err < 0) + return (SNMP_CODE_EDECRYPT); + else if (err == 0) + return (SNMP_CODE_OK); + + if (EVP_EncryptInit(&ctx, ctype, pdu->user.priv_key, iv) != 1) + return (SNMP_CODE_FAILED); + + if (EVP_EncryptUpdate(&ctx, pdu->scoped_ptr, &olen, pdu->scoped_ptr, + pdu->scoped_len) != 1 || + EVP_EncryptFinal(&ctx, pdu->scoped_ptr + olen, &olen) != 1) { + EVP_CIPHER_CTX_cleanup(&ctx); + return (SNMP_CODE_FAILED); + } + + EVP_CIPHER_CTX_cleanup(&ctx); + return (SNMP_CODE_OK); +} + +enum snmp_code +snmp_pdu_decrypt(const struct snmp_pdu *pdu) +{ + int32_t err, olen; + uint8_t iv[SNMP_PRIV_AES_IV_SIZ]; + const EVP_CIPHER *ctype; + EVP_CIPHER_CTX ctx; + + err = snmp_pdu_cipher_init(pdu, pdu->scoped_len, &ctype, iv); + if (err < 0) + return (SNMP_CODE_EDECRYPT); + else if (err == 0) + return (SNMP_CODE_OK); + + if (EVP_DecryptInit(&ctx, ctype, pdu->user.priv_key, iv) != 1 || + EVP_CIPHER_CTX_set_padding(&ctx, 0) != 1) + return (SNMP_CODE_EDECRYPT); + + if (EVP_DecryptUpdate(&ctx, pdu->scoped_ptr, &olen, pdu->scoped_ptr, + pdu->scoped_len) != 1 || + EVP_DecryptFinal(&ctx, pdu->scoped_ptr + olen, &olen) != 1) { + EVP_CIPHER_CTX_cleanup(&ctx); + return (SNMP_CODE_EDECRYPT); + } + + EVP_CIPHER_CTX_cleanup(&ctx); + return (SNMP_CODE_OK); +} + +/* [RFC 3414] - A.2. Password to Key Algorithm */ +enum snmp_code +snmp_passwd_to_keys(struct snmp_user *user, char *passwd) +{ + int err, loop, i, pwdlen; + uint32_t keylen, olen; + const EVP_MD *dtype; + EVP_MD_CTX ctx; + uint8_t authbuf[SNMP_AUTH_BUF_SIZE]; + + if (passwd == NULL || user == NULL) + return (SNMP_CODE_FAILED); + + err = snmp_digest_init(user, &ctx, &dtype, &keylen); + if (err < 0) + return (SNMP_CODE_BADDIGEST); + else if (err == 0) + return (SNMP_CODE_OK); + + memset(user->auth_key, 0, sizeof(user->auth_key)); + pwdlen = strlen(passwd); + + for (loop = 0; loop < SNMP_AUTH_KEY_LOOPCNT; loop += i) { + for (i = 0; i < SNMP_EXTENDED_KEY_SIZ; i++) + authbuf[i] = passwd[(loop + i) % pwdlen]; + if (EVP_DigestUpdate(&ctx, authbuf, SNMP_EXTENDED_KEY_SIZ) != 1) + goto failed; + } + + if (EVP_DigestFinal(&ctx, user->auth_key, &olen) != 1) + goto failed; + + EVP_MD_CTX_cleanup(&ctx); + return (SNMP_CODE_OK); + +failed: + EVP_MD_CTX_cleanup(&ctx); + return (SNMP_CODE_BADDIGEST); +} + +/* [RFC 3414] - 2.6. Key Localization Algorithm */ +enum snmp_code +snmp_get_local_keys(struct snmp_user *user, uint8_t *eid, uint32_t elen) +{ + int err; + uint32_t keylen, olen; + const EVP_MD *dtype; + EVP_MD_CTX ctx; + uint8_t authbuf[SNMP_AUTH_BUF_SIZE]; + + if (user == NULL || eid == NULL || elen > SNMP_ENGINE_ID_SIZ) + return (SNMP_CODE_FAILED); + + memset(user->priv_key, 0, sizeof(user->priv_key)); + memset(authbuf, 0, sizeof(authbuf)); + + err = snmp_digest_init(user, &ctx, &dtype, &keylen); + if (err < 0) + return (SNMP_CODE_BADDIGEST); + else if (err == 0) + return (SNMP_CODE_OK); + + memcpy(authbuf, user->auth_key, keylen); + memcpy(authbuf + keylen, eid, elen); + memcpy(authbuf + keylen + elen, user->auth_key, keylen); + + if (EVP_DigestUpdate(&ctx, authbuf, 2 * keylen + elen) != 1 || + EVP_DigestFinal(&ctx, user->auth_key, &olen) != 1) { + EVP_MD_CTX_cleanup(&ctx); + return (SNMP_CODE_BADDIGEST); + } + EVP_MD_CTX_cleanup(&ctx); + + if (user->priv_proto != SNMP_PRIV_NOPRIV) + memcpy(user->priv_key, user->auth_key, sizeof(user->priv_key)); + + return (SNMP_CODE_OK); +} + +enum snmp_code +snmp_calc_keychange(struct snmp_user *user, uint8_t *keychange) +{ + int32_t err, rvalue[SNMP_AUTH_HMACSHA_KEY_SIZ / 4]; + uint32_t i, keylen, olen; + const EVP_MD *dtype; + EVP_MD_CTX ctx; + + err = snmp_digest_init(user, &ctx, &dtype, &keylen); + if (err < 0) + return (SNMP_CODE_BADDIGEST); + else if (err == 0) + return (SNMP_CODE_OK); + + for (i = 0; i < keylen / 4; i++) + rvalue[i] = random(); + + memcpy(keychange, user->auth_key, keylen); + memcpy(keychange + keylen, rvalue, keylen); + + if (EVP_DigestUpdate(&ctx, keychange, 2 * keylen) != 1 || + EVP_DigestFinal(&ctx, keychange, &olen) != 1) { + EVP_MD_CTX_cleanup(&ctx); + return (SNMP_CODE_BADDIGEST); + } + + EVP_MD_CTX_cleanup(&ctx); + return (SNMP_CODE_OK); +} + +#else /* !HAVE_LIBCRYPTO */ + +enum snmp_code +snmp_pdu_calc_digest(const struct snmp_pdu *pdu, uint8_t *digest __unused) +{ + if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH) + return (SNMP_CODE_BADSECLEVEL); + + + return (SNMP_CODE_OK); +} + +enum snmp_code +snmp_pdu_encrypt(const struct snmp_pdu *pdu) +{ + if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV) + return (SNMP_CODE_BADSECLEVEL); + + return (SNMP_CODE_OK); +} + +enum snmp_code +snmp_pdu_decrypt(const struct snmp_pdu *pdu) +{ + if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV) + return (SNMP_CODE_BADSECLEVEL); + + return (SNMP_CODE_OK); +} + +enum snmp_code +snmp_passwd_to_keys(struct snmp_user *user, char *passwd __unused) +{ + if (user->auth_proto == SNMP_AUTH_NOAUTH && + user->priv_proto == SNMP_PRIV_NOPRIV) + return (SNMP_CODE_OK); + + errno = EPROTONOSUPPORT; + + return (SNMP_CODE_FAILED); +} + +enum snmp_code +snmp_get_local_keys(struct snmp_user *user, uint8_t *eid __unused, + uint32_t elen __unused) +{ + if (user->auth_proto == SNMP_AUTH_NOAUTH && + user->priv_proto == SNMP_PRIV_NOPRIV) + return (SNMP_CODE_OK); + + errno = EPROTONOSUPPORT; + + return (SNMP_CODE_FAILED); +} + +enum snmp_code +snmp_calc_keychange(struct snmp_user *user __unused, + uint8_t *keychange __unused) +{ + errno = EPROTONOSUPPORT; + return (SNMP_CODE_FAILED); +} + +#endif /* HAVE_LIBCRYPTO */ Property changes on: vendor/bsnmp/1.13/lib/snmpcrypto.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/snmppriv.h =================================================================== --- vendor/bsnmp/1.13/lib/snmppriv.h (nonexistent) +++ vendor/bsnmp/1.13/lib/snmppriv.h (revision 336778) @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/lib/snmppriv.h,v 1.9 2004/08/06 08:46:58 brandt Exp $ + * + * Private functions. + */ +#include + +enum asn_err snmp_binding_encode(struct asn_buf *, const struct snmp_value *); +enum snmp_code snmp_pdu_encode_header(struct asn_buf *, struct snmp_pdu *); +enum snmp_code snmp_fix_encoding(struct asn_buf *, struct snmp_pdu *); +enum asn_err snmp_parse_pdus_hdr(struct asn_buf *b, struct snmp_pdu *pdu, + asn_len_t *lenp); + +enum snmp_code snmp_pdu_calc_digest(const struct snmp_pdu *, uint8_t *); +enum snmp_code snmp_pdu_encrypt(const struct snmp_pdu *); +enum snmp_code snmp_pdu_decrypt(const struct snmp_pdu *); + +#define DEFAULT_HOST "localhost" +#define DEFAULT_PORT "snmp" +#define DEFAULT_LOCAL "/var/run/snmp.sock" Property changes on: vendor/bsnmp/1.13/lib/snmppriv.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/snmptc.h.in =================================================================== --- vendor/bsnmp/1.13/lib/snmptc.h.in (nonexistent) +++ vendor/bsnmp/1.13/lib/snmptc.h.in (revision 336778) @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2018 The FreeBSD Foundation + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef snmptc_h_1529923773 +#define snmptc_h_1529923773 + +@tc@ + +/** + * Check whether a row status is ok. + * + * \param s row status + * + * \return true if value is ok, false otherwise + */ +static inline int +isok_RowStatus(enum RowStatus s) +{ + return s >= RowStatus_active && s <= RowStatus_destroy; +} + +/** + * Make string out of a row status. + * + * \param s row status + * + * \return string version; if the value is not a legal status + * return "RowStatus???" + */ +static inline const char * +tostr_RowStatus(enum RowStatus s) +{ + static const char *vals[] = { STRING_RowStatus }; + + if (isok_RowStatus(s)) + return vals[(int)s - STROFF_RowStatus]; + return ("RowStatus???"); +} + +#endif Property changes on: vendor/bsnmp/1.13/lib/snmptc.h.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/support.c =================================================================== --- vendor/bsnmp/1.13/lib/support.c (nonexistent) +++ vendor/bsnmp/1.13/lib/support.c (revision 336778) @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2004 + * Hartmut Brandt. + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/lib/support.c,v 1.1 2004/08/06 08:47:58 brandt Exp $ + * + * Functions that are missing on certain systems. + */ +#include +#include +#include +#include +#include +#include "support.h" + +#ifndef HAVE_ERR_H + +void +warnx(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + fprintf(stderr, "warning: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +void +warn(const char *fmt, ...) +{ + va_list ap; + int e = errno; + + va_start(ap, fmt); + fprintf(stderr, "warning: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ": %s\n", strerror(e)); + va_end(ap); +} + +void +errx(int code, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + fprintf(stderr, "error: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(code); +} + +void +err(int code, const char *fmt, ...) +{ + va_list ap; + int e = errno; + + va_start(ap, fmt); + fprintf(stderr, "error: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ": %s\n", strerror(e)); + va_end(ap); + exit(code); +} + +#endif + +#ifndef HAVE_STRLCPY + +size_t +strlcpy(char *dst, const char *src, size_t len) +{ + size_t ret = strlen(dst); + + while (len > 1) { + *dst++ = *src++; + len--; + } + if (len > 0) + *dst = '\0'; + return (ret); +} + +#endif + +#ifndef HAVE_GETADDRINFO + +#include +#include +#include +#include + +extern int h_nerr; +extern int h_errno; +extern const char *h_errlist[]; + +/* + * VERY poor man's implementation + */ +int +getaddrinfo(const char *host, const char *port, const struct addrinfo *hints, + struct addrinfo **res) +{ + struct hostent *hent; + struct sockaddr_in *s; + struct servent *sent; + + if ((hent = gethostbyname(host)) == NULL) + return (h_errno); + if (hent->h_addrtype != hints->ai_family) + return (HOST_NOT_FOUND); + if (hent->h_addrtype != AF_INET) + return (HOST_NOT_FOUND); + + if ((*res = malloc(sizeof(**res))) == NULL) + return (HOST_NOT_FOUND); + + (*res)->ai_flags = hints->ai_flags; + (*res)->ai_family = hints->ai_family; + (*res)->ai_socktype = hints->ai_socktype; + (*res)->ai_protocol = hints->ai_protocol; + (*res)->ai_next = NULL; + + if (((*res)->ai_addr = malloc(sizeof(struct sockaddr_in))) == NULL) { + freeaddrinfo(*res); + return (HOST_NOT_FOUND); + } + (*res)->ai_addrlen = sizeof(struct sockaddr_in); + s = (struct sockaddr_in *)(*res)->ai_addr; + s->sin_family = hints->ai_family; + s->sin_len = sizeof(*s); + memcpy(&s->sin_addr, hent->h_addr, 4); + + if ((sent = getservbyname(port, NULL)) == NULL) { + freeaddrinfo(*res); + return (HOST_NOT_FOUND); + } + s->sin_port = sent->s_port; + + return (0); +} + +const char * +gai_strerror(int e) +{ + + if (e < 0 || e >= h_nerr) + return ("unknown error"); + return (h_errlist[e]); +} + +void +freeaddrinfo(struct addrinfo *p) +{ + struct addrinfo *next; + + while (p != NULL) { + next = p->ai_next; + if (p->ai_addr != NULL) + free(p->ai_addr); + free(p); + p = next; + } +} + +#endif Property changes on: vendor/bsnmp/1.13/lib/support.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/support.h =================================================================== --- vendor/bsnmp/1.13/lib/support.h (nonexistent) +++ vendor/bsnmp/1.13/lib/support.h (revision 336778) @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2004-2005 + * Hartmut Brandt. + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/lib/support.h,v 1.2 2005/10/06 07:14:59 brandt_h Exp $ + * + * Functions that are missing on certain systems. This header file is not + * to be installed. + */ +#ifndef bsnmp_support_h_ +#define bsnmp_support_h_ + +#include + +#ifndef HAVE_ERR_H +void err(int, const char *, ...) __printflike(2, 3) __dead2; +void errx(int, const char *, ...) __printflike(2, 3) __dead2; + +void warn(const char *, ...) __printflike(1, 2); +void warnx(const char *, ...) __printflike(1, 2); +#endif + +#ifndef HAVE_STRLCPY +size_t strlcpy(char *, const char *, size_t); +#endif + +#ifndef HAVE_GETADDRINFO + +struct addrinfo { + u_int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + struct sockaddr *ai_addr; + int ai_addrlen; + struct addrinfo *ai_next; +}; +#define AI_CANONNAME 0x0001 + +int getaddrinfo(const char *, const char *, const struct addrinfo *, + struct addrinfo **); +const char *gai_strerror(int); +void freeaddrinfo(struct addrinfo *); + +#endif + +/* + * For systems with missing stdint.h or inttypes.h + */ +#if !defined(INT32_MIN) +#define INT32_MIN (-0x7fffffff-1) +#endif +#if !defined(INT32_MAX) +#define INT32_MAX (0x7fffffff) +#endif +#if !defined(UINT32_MAX) +#define UINT32_MAX (0xffffffff) +#endif + +/* + * Systems missing SA_SIZE(). Taken from FreeBSD net/route.h:1.63 + */ +#ifndef SA_SIZE + +#define SA_SIZE(sa) \ + ( (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \ + sizeof(long) : \ + 1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) ) + +#endif + +#endif Property changes on: vendor/bsnmp/1.13/lib/support.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/lib/tc.def =================================================================== --- vendor/bsnmp/1.13/lib/tc.def (nonexistent) +++ vendor/bsnmp/1.13/lib/tc.def (revision 336778) @@ -0,0 +1,48 @@ +#- +# Copyright (C) 2010 The FreeBSD Foundation +# All rights reserved. +# +# This software was developed by Shteryana Sotirova Shopova under +# sponsorship from the FreeBSD Foundation. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +typedef RowStatus ENUM ( + 1 active + 2 notInService + 3 notReady + 4 createAndGo + 5 createAndWait + 6 destroy +) + +typedef StorageType ENUM ( + 1 other + 2 volatile + 3 nonVolatile + 4 permanent + 5 readOnly +) + Property changes on: vendor/bsnmp/1.13/lib/tc.def ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/libbsnmp.pc.in =================================================================== --- vendor/bsnmp/1.13/libbsnmp.pc.in (nonexistent) +++ vendor/bsnmp/1.13/libbsnmp.pc.in (revision 336778) @@ -0,0 +1,12 @@ +# $Id: libbegemot.pc.in 31 2015-07-15 13:07:02Z kato_zo $ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +includedir=@includedir@ +libdir=@libdir@ + +Name: libbegemot +Description: Library for storing the rpoll code +Version: 0.0.0 +Requires: +Cflags: -I${includedir} +Libs: -L${libdir} -lbsnmp Property changes on: vendor/bsnmp/1.13/libbsnmp.pc.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/oid-list =================================================================== --- vendor/bsnmp/1.13/oid-list (nonexistent) +++ vendor/bsnmp/1.13/oid-list (revision 336778) @@ -0,0 +1,44 @@ +$Begemot: bsnmp/trunk/oid-list 1512 2011-02-03 15:16:22Z brandt_h $ + +This file documents the OID assignments under BSNMP's private OID. + +While I was at Fraunhofer Fokus (www.fokus.fraunhofer.de) I registered +an official OID for Fokus: enterprises 12325 and assigned the sub-OID 1 +to the software I develop. Under this OID there are: + +enterprises + 12325 FOKUS + 1 BEGEMOT + 1 BEGEMOT-SNMPD + 2 BEGEMOT-NETGRAPH snmpd netgraph module + 3 BEGEMOT-IP snmpd IP related stuff. + 4 BEGEMOT-IFACE-MIB interface MIB private stuff + 5 BEGEMOT-IPSTATS-MIB IP statistics + 6 BEGEMOT-IP-MIB IP objects + 100 BEGEMOT-ILMID snmpd ILMID module + 101 BEGEMOT-ATM snmpd ATM module + 200 BEGEMOT-PF snmpd PF module (phillip@freebsd.org) + 201 BEGEMOT-NTP snmpd NTP module + 202 BEGEMOT-HOSTRES snmpd HOSTRES module private stuff + 203 regexData bsnmp-regex (Nate Nielsen ) + 204 pingData bsnmp-ping (Nate Nielsen ) + 205 begemotBridge bridge module + 210 begemotWlan WLAN module + 220 begemotHast HAST module + + 300 BEGEMOT-ACM DLR ACM project + 303 BEGEMOT-WLINK DLR WLINK simulator + 304 BEGEMOT-SATX DLR SatX simulator + + 405 mysql (vanilla@fatpipi.com) + 406 varnish (vanilla@fatpipi.com) + + 500 DLR-MOSAKA DLR Mosaka simulation platform + + 1111 bsnmp-jails per-jail network, cpu, disk, memory statistics (Stef Walter ) + 1112 bsnmp-pcap monitor traffic for specific network flows (Stef Walter ) + +If you need an OID and don't know where to stuck it in, I can assign you one - +just drop me a mail. + +harti Property changes on: vendor/bsnmp/1.13/oid-list ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/BEGEMOT-IP-MIB.txt =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/BEGEMOT-IP-MIB.txt (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/BEGEMOT-IP-MIB.txt (revision 336778) @@ -0,0 +1,64 @@ +-- +-- Copyright (c) 2006 +-- Hartmut Brandt +-- All rights reserved. +-- +-- Author: Harti Brandt +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- 1. Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- 2. Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +-- ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +-- SUCH DAMAGE. +-- +-- $Begemot: bsnmp/snmp_mibII/BEGEMOT-IP-MIB.txt,v 1.1 2006/02/14 09:04:18 brandt_h Exp $ +-- +-- Private MIB for IP stuff. +-- +BEGEMOT-IP-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY + FROM SNMPv2-SMI + begemot + FROM BEGEMOT-MIB; + +begemotIp MODULE-IDENTITY + LAST-UPDATED "200602130000Z" + ORGANIZATION "German Aerospace Center" + CONTACT-INFO + " Hartmut Brandt + + Postal: German Aerospace Center + Oberpfaffenhofen + 82234 Wessling + Germany + + Fax: +49 8153 28 2843 + + E-mail: harti@freebsd.org" + DESCRIPTION + "The MIB for IP stuff that is not in the official IP MIBs." + REVISION "200602130000Z" + DESCRIPTION + "Initial revision." + ::= { begemot 3 } + +begemotIpObjects OBJECT IDENTIFIER ::= { begemotIp 1 } + +END Property changes on: vendor/bsnmp/1.13/snmp_mibII/BEGEMOT-IP-MIB.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/BEGEMOT-MIB2-MIB.txt =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/BEGEMOT-MIB2-MIB.txt (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/BEGEMOT-MIB2-MIB.txt (revision 336778) @@ -0,0 +1,106 @@ +-- +-- Copyright (c) 2006 +-- Hartmut Brandt +-- All rights reserved. +-- +-- Author: Harti Brandt +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- 1. Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- 2. Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +-- ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +-- SUCH DAMAGE. +-- +-- $Begemot: bsnmp/snmp_mibII/BEGEMOT-MIB2-MIB.txt,v 1.1 2006/02/14 09:04:18 brandt_h Exp $ +-- +-- Private MIB for MIB2. +-- +BEGEMOT-MIB2-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, TimeTicks, Counter64 + FROM SNMPv2-SMI + begemotIp + FROM BEGEMOT-IP-MIB; + +begemotMib2 MODULE-IDENTITY + LAST-UPDATED "200908030000Z" + ORGANIZATION "German Aerospace Center" + CONTACT-INFO + " Hartmut Brandt + + Postal: German Aerospace Center + Oberpfaffenhofen + 82234 Wessling + Germany + + Fax: +49 8153 28 2843 + + E-mail: harti@freebsd.org" + DESCRIPTION + "The MIB for private mib2 stuff." + REVISION "200908030000Z" + DESCRIPTION + "Second edition adds begemotIfDataPoll object." + REVISION "200602130000Z" + DESCRIPTION + "Initial revision." + ::= { begemotIp 1 } + +begemotIfMaxspeed OBJECT-TYPE + SYNTAX Counter64 + UNITS "bps" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The speed of the fastest interface in ifTable in bps." + ::= { begemotMib2 1 } + +begemotIfPoll OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The current polling rate for the HC 64-bit counters." + ::= { begemotMib2 2 } + +begemotIfForcePoll OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The polling rate to be enforced for the HC 64-bit counters. + If this value is 0 the mib2 module computes a polling rate + depending on the value of begemotIfMaxspeed. If this value + turns out to be wrong, the polling rate can be force to an + arbitrary value by setting begemotIfForcePoll to a non-0 + value. This may be necessary if an interface announces a wrong + bit rate in its MIB." + ::= { begemotMib2 3 } + +begemotIfDataPoll OBJECT-TYPE + SYNTAX TimeTicks + UNITS "deciseconds" + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The rate at which the mib2 module will poll interface data." + DEFVAL { 100 } + ::= { begemotMib2 4 } + +END Property changes on: vendor/bsnmp/1.13/snmp_mibII/BEGEMOT-MIB2-MIB.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/Makefile.in =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/Makefile.in (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/Makefile.in (revision 336778) @@ -0,0 +1,48 @@ +# Copyright (c) 2004-2009,2018 +# Hartmut Brandt +# All rights reserved. +# Copyright (c) 2003 +# Fraunhofer Institute for Open Communication Systems (FhG Fokus). +# All rights reserved. +# +# Author: Harti Brandt +# +# $Begemot: bsnmp/trunk/snmp_mibII/Makefile.in 1492 2009-11-21 18:56:19Z brandt_h $ +# +MOD= mibII +SRCS= ${MOD}_tree.c mibII.c mibII_begemot.c mibII_ifmib.c mibII_ifstack.c \ + mibII_interfaces.c mibII_ip.c mibII_ipaddr.c mibII_nettomedia.c \ + mibII_rcvaddr.c mibII_route.c mibII_tcp.c mibII_udp.c +INCS= snmp_${MOD}.h +DEFS= mibII_tree.def +MAN3= snmp_mibII.3 +MANFILTER= sed -e 's%@MODPATH@%${LIBDIR}/%g' \ + -e 's%@DEFPATH@%${DEFSDIR}/%g' \ + -e 's%@MIBSPATH@%${MIBSDIR}/%g' + +XSYM= ipAddrTable ifTable ifRcvAddressEntry ifMIB ipMIB tcpMIB udpMIB \ + ipForward ifIndex linkDown linkUp + +BMIBS= BEGEMOT-IP-MIB.txt BEGEMOT-MIB2-MIB.txt +DEFS= mibII_tree.def +INCS= snmp_mibII.h + +LIB= snmp_${MOD}.la +SHLIB_MAJOR= 3 +SHLIB_MINOR= 0 + +CFLAGS+= -I$(srcdir) -I$(srcdir)/../lib -I$(builddir) -I$(srcdir)/../snmpd + +CLEANFILES += ${MOD}_oid.h ${MOD}_tree.c ${MOD}_tree.h *.3out + +# for bootstrapping +GENSNMPTREE= $(builddir)/../gensnmptree/gensnmptree -I${srcdir}/../lib + +$(LIB): ${MOD}_oid.h ${MOD}_tree.h $(SRCS:.c=.lo) + $(LIBTOOL) --mode=link $(CC) $(LDLAGS) -module -o $@ $(SRCS:.c=.lo) -rpath $(libdir) -version-info $(SHLIB_MAJOR):$(SHLIB_MINOR) + +${MOD}_oid.h: ${MOD}_tree.def + ${GENSNMPTREE} <${srcdir}/${MOD}_tree.def -e ${XSYM} >$@ + +${MOD}_tree.h ${MOD}_tree.c : ${MOD}_tree.def + ${GENSNMPTREE} <${srcdir}/${MOD}_tree.def -l -p ${MOD}_ Property changes on: vendor/bsnmp/1.13/snmp_mibII/Makefile.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/mibII.c =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/mibII.c (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/mibII.c (revision 336778) @@ -0,0 +1,1814 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: mibII.c 516 2006-10-27 15:54:02Z brandt_h $ + * + * Implementation of the standard interfaces and ip MIB. + */ +#include "mibII.h" +#include "mibII_oid.h" +#include +#include + + +/*****************************/ + +/* our module */ +static struct lmodule *module; + +/* routing socket */ +static int route; +static void *route_fd; + +/* if-index allocator */ +static uint32_t next_if_index = 1; + +/* currently fetching the arp table */ +static int in_update_arp; + +/* OR registrations */ +static u_int ifmib_reg; +static u_int ipmib_reg; +static u_int tcpmib_reg; +static u_int udpmib_reg; +static u_int ipForward_reg; + +/*****************************/ + +/* list of all IP addresses */ +struct mibifa_list mibifa_list = TAILQ_HEAD_INITIALIZER(mibifa_list); + +/* list of all interfaces */ +struct mibif_list mibif_list = TAILQ_HEAD_INITIALIZER(mibif_list); + +/* list of dynamic interface names */ +struct mibdynif_list mibdynif_list = SLIST_HEAD_INITIALIZER(mibdynif_list); + +/* list of all interface index mappings */ +struct mibindexmap_list mibindexmap_list = STAILQ_HEAD_INITIALIZER(mibindexmap_list); + +/* list of all stacking entries */ +struct mibifstack_list mibifstack_list = TAILQ_HEAD_INITIALIZER(mibifstack_list); + +/* list of all receive addresses */ +struct mibrcvaddr_list mibrcvaddr_list = TAILQ_HEAD_INITIALIZER(mibrcvaddr_list); + +/* list of all NetToMedia entries */ +struct mibarp_list mibarp_list = TAILQ_HEAD_INITIALIZER(mibarp_list); + +/* number of interfaces */ +int32_t mib_if_number; + +/* last change of table */ +uint64_t mib_iftable_last_change; + +/* last change of stack table */ +uint64_t mib_ifstack_last_change; + +/* if this is set, one of our lists may be bad. refresh them when idle */ +int mib_iflist_bad; + +/* network socket */ +int mib_netsock; + +/* last time refreshed */ +uint64_t mibarpticks; + +/* info on system clocks */ +struct clockinfo clockinfo; + +/* list of all New if registrations */ +static struct newifreg_list newifreg_list = TAILQ_HEAD_INITIALIZER(newifreg_list); + +/* baud rate of fastest interface */ +uint64_t mibif_maxspeed; + +/* user-forced update interval */ +u_int mibif_force_hc_update_interval; + +/* current update interval */ +u_int mibif_hc_update_interval; + +/* HC update timer handle */ +static void *hc_update_timer; + +/* Idle poll timer */ +static void *mibII_poll_timer; + +/* interfaces' data poll interval */ +u_int mibII_poll_ticks; + +/* Idle poll hook */ +static void mibII_idle(void *arg __unused); + +/*****************************/ + +static const struct asn_oid oid_ifMIB = OIDX_ifMIB; +static const struct asn_oid oid_ipMIB = OIDX_ipMIB; +static const struct asn_oid oid_tcpMIB = OIDX_tcpMIB; +static const struct asn_oid oid_udpMIB = OIDX_udpMIB; +static const struct asn_oid oid_ipForward = OIDX_ipForward; +static const struct asn_oid oid_linkDown = OIDX_linkDown; +static const struct asn_oid oid_linkUp = OIDX_linkUp; +static const struct asn_oid oid_ifIndex = OIDX_ifIndex; + +/*****************************/ + +/* + * Find an interface + */ +struct mibif * +mib_find_if(u_int idx) +{ + struct mibif *ifp; + + TAILQ_FOREACH(ifp, &mibif_list, link) + if (ifp->index == idx) + return (ifp); + return (NULL); +} + +struct mibif * +mib_find_if_sys(u_int sysindex) +{ + struct mibif *ifp; + + TAILQ_FOREACH(ifp, &mibif_list, link) + if (ifp->sysindex == sysindex) + return (ifp); + return (NULL); +} + +struct mibif * +mib_find_if_name(const char *name) +{ + struct mibif *ifp; + + TAILQ_FOREACH(ifp, &mibif_list, link) + if (strcmp(ifp->name, name) == 0) + return (ifp); + return (NULL); +} + +/* + * Check whether an interface is dynamic. The argument may include the + * unit number. This assumes, that the name part does NOT contain digits. + */ +int +mib_if_is_dyn(const char *name) +{ + size_t len; + struct mibdynif *d; + + for (len = 0; name[len] != '\0' && isalpha(name[len]) ; len++) + ; + SLIST_FOREACH(d, &mibdynif_list, link) + if (strlen(d->name) == len && strncmp(d->name, name, len) == 0) + return (1); + return (0); +} + +/* set an interface name to dynamic mode */ +void +mib_if_set_dyn(const char *name) +{ + struct mibdynif *d; + + SLIST_FOREACH(d, &mibdynif_list, link) + if (strcmp(name, d->name) == 0) + return; + if ((d = malloc(sizeof(*d))) == NULL) + err(1, NULL); + strlcpy(d->name, name, sizeof(d->name)); + SLIST_INSERT_HEAD(&mibdynif_list, d, link); +} + +/* + * register for interface creations + */ +int +mib_register_newif(int (*func)(struct mibif *), const struct lmodule *mod) +{ + struct newifreg *reg; + + TAILQ_FOREACH(reg, &newifreg_list, link) + if (reg->mod == mod) { + reg->func = func; + return (0); + } + if ((reg = malloc(sizeof(*reg))) == NULL) { + syslog(LOG_ERR, "newifreg: %m"); + return (-1); + } + reg->mod = mod; + reg->func = func; + TAILQ_INSERT_TAIL(&newifreg_list, reg, link); + + return (0); +} + +void +mib_unregister_newif(const struct lmodule *mod) +{ + struct newifreg *reg; + + TAILQ_FOREACH(reg, &newifreg_list, link) + if (reg->mod == mod) { + TAILQ_REMOVE(&newifreg_list, reg, link); + free(reg); + return; + } + +} + +struct mibif * +mib_first_if(void) +{ + return (TAILQ_FIRST(&mibif_list)); +} +struct mibif * +mib_next_if(const struct mibif *ifp) +{ + return (TAILQ_NEXT(ifp, link)); +} + +/* + * Change the admin status of an interface + */ +int +mib_if_admin(struct mibif *ifp, int up) +{ + struct ifreq ifr; + + strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); + if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr) == -1) { + syslog(LOG_ERR, "SIOCGIFFLAGS(%s): %m", ifp->name); + return (-1); + } + if (up) + ifr.ifr_flags |= IFF_UP; + else + ifr.ifr_flags &= ~IFF_UP; + if (ioctl(mib_netsock, SIOCSIFFLAGS, &ifr) == -1) { + syslog(LOG_ERR, "SIOCSIFFLAGS(%s): %m", ifp->name); + return (-1); + } + + (void)mib_fetch_ifmib(ifp); + + return (0); +} + +/* + * Generate a link up/down trap + */ +static void +link_trap(struct mibif *ifp, int up) +{ + struct snmp_value ifindex; + + ifindex.var = oid_ifIndex; + ifindex.var.subs[ifindex.var.len++] = ifp->index; + ifindex.syntax = SNMP_SYNTAX_INTEGER; + ifindex.v.integer = ifp->index; + + snmp_send_trap(up ? &oid_linkUp : &oid_linkDown, &ifindex, + (struct snmp_value *)NULL); +} + +/** + * Fetch the GENERIC IFMIB and update the HC counters + */ +static int +fetch_generic_mib(struct mibif *ifp, const struct ifmibdata *old) +{ + int name[6]; + size_t len; + struct mibif_private *p = ifp->private; + + name[0] = CTL_NET; + name[1] = PF_LINK; + name[2] = NETLINK_GENERIC; + name[3] = IFMIB_IFDATA; + name[4] = ifp->sysindex; + name[5] = IFDATA_GENERAL; + + len = sizeof(ifp->mib); + if (sysctl(name, nitems(name), &ifp->mib, &len, NULL, 0) == -1) { + if (errno != ENOENT) + syslog(LOG_WARNING, "sysctl(ifmib, %s) failed %m", + ifp->name); + return (-1); + } + + /* + * Assume that one of the two following compounds is optimized away + */ + if (ULONG_MAX >= 0xffffffffffffffffULL) { + p->hc_inoctets = ifp->mib.ifmd_data.ifi_ibytes; + p->hc_outoctets = ifp->mib.ifmd_data.ifi_obytes; + p->hc_omcasts = ifp->mib.ifmd_data.ifi_omcasts; + p->hc_opackets = ifp->mib.ifmd_data.ifi_opackets; + p->hc_imcasts = ifp->mib.ifmd_data.ifi_imcasts; + p->hc_ipackets = ifp->mib.ifmd_data.ifi_ipackets; + + } else if (ULONG_MAX >= 0xffffffff) { + +#define UPDATE(HC, MIB) \ + if (old->ifmd_data.MIB > ifp->mib.ifmd_data.MIB) \ + p->HC += (0x100000000ULL + \ + ifp->mib.ifmd_data.MIB) - \ + old->ifmd_data.MIB; \ + else \ + p->HC += ifp->mib.ifmd_data.MIB - \ + old->ifmd_data.MIB; + + UPDATE(hc_inoctets, ifi_ibytes) + UPDATE(hc_outoctets, ifi_obytes) + UPDATE(hc_omcasts, ifi_omcasts) + UPDATE(hc_opackets, ifi_opackets) + UPDATE(hc_imcasts, ifi_imcasts) + UPDATE(hc_ipackets, ifi_ipackets) + +#undef UPDATE + } else + abort(); + return (0); +} + +/** + * Update the 64-bit interface counters + */ +static void +update_hc_counters(void *arg __unused) +{ + struct mibif *ifp; + struct ifmibdata oldmib; + + TAILQ_FOREACH(ifp, &mibif_list, link) { + oldmib = ifp->mib; + (void)fetch_generic_mib(ifp, &oldmib); + } +} + +/** + * Recompute the poll timer for the HC counters + */ +void +mibif_reset_hc_timer(void) +{ + u_int ticks; + + if ((ticks = mibif_force_hc_update_interval) == 0) { + if (mibif_maxspeed <= IF_Mbps(10)) { + /* at 10Mbps overflow needs 3436 seconds */ + ticks = 3000 * 100; /* 50 minutes */ + } else if (mibif_maxspeed <= IF_Mbps(100)) { + /* at 100Mbps overflow needs 343 seconds */ + ticks = 300 * 100; /* 5 minutes */ + } else if (mibif_maxspeed < IF_Mbps(622)) { + /* at 622Mbps overflow needs 53 seconds */ + ticks = 40 * 100; /* 40 seconds */ + } else if (mibif_maxspeed <= IF_Mbps(1000)) { + /* at 1Gbps overflow needs 34 seconds */ + ticks = 20 * 100; /* 20 seconds */ + } else { + /* at 10Gbps overflow needs 3.4 seconds */ + ticks = 100; /* 1 seconds */ + } + } + + if (ticks == mibif_hc_update_interval) + return; + + if (hc_update_timer != NULL) { + timer_stop(hc_update_timer); + hc_update_timer = NULL; + } + update_hc_counters(NULL); + if ((hc_update_timer = timer_start_repeat(ticks * 10, ticks * 10, + update_hc_counters, NULL, module)) == NULL) { + syslog(LOG_ERR, "timer_start(%u): %m", ticks); + return; + } + mibif_hc_update_interval = ticks; +} + +/** + * Restart the idle poll timer. + */ +void +mibif_restart_mibII_poll_timer(void) +{ + if (mibII_poll_timer != NULL) + timer_stop(mibII_poll_timer); + + if ((mibII_poll_timer = timer_start_repeat(mibII_poll_ticks * 10, + mibII_poll_ticks * 10, mibII_idle, NULL, module)) == NULL) + syslog(LOG_ERR, "timer_start(%u): %m", mibII_poll_ticks); +} + +/* + * Fetch new MIB data. + */ +int +mib_fetch_ifmib(struct mibif *ifp) +{ + int name[6]; + size_t len; + void *newmib; + struct ifmibdata oldmib = ifp->mib; + struct ifreq irr; + + if (fetch_generic_mib(ifp, &oldmib) == -1) + return (-1); + + /* + * Quoting RFC2863, 3.1.15: "... LinkUp and linkDown traps are + * generated just after ifOperStatus leaves, or just before it + * enters, the down state, respectively;" + */ + if (ifp->trap_enable && ifp->mib.ifmd_data.ifi_link_state != + oldmib.ifmd_data.ifi_link_state && + (ifp->mib.ifmd_data.ifi_link_state == LINK_STATE_DOWN || + oldmib.ifmd_data.ifi_link_state == LINK_STATE_DOWN)) + link_trap(ifp, ifp->mib.ifmd_data.ifi_link_state == + LINK_STATE_UP ? 1 : 0); + + ifp->flags &= ~(MIBIF_HIGHSPEED | MIBIF_VERYHIGHSPEED); + if (ifp->mib.ifmd_data.ifi_baudrate > 20000000) { + ifp->flags |= MIBIF_HIGHSPEED; + if (ifp->mib.ifmd_data.ifi_baudrate > 650000000) + ifp->flags |= MIBIF_VERYHIGHSPEED; + } + if (ifp->mib.ifmd_data.ifi_baudrate > mibif_maxspeed) { + mibif_maxspeed = ifp->mib.ifmd_data.ifi_baudrate; + mibif_reset_hc_timer(); + } + + /* + * linkspecific MIB + */ + name[0] = CTL_NET; + name[1] = PF_LINK; + name[2] = NETLINK_GENERIC; + name[3] = IFMIB_IFDATA; + name[4] = ifp->sysindex; + name[5] = IFDATA_LINKSPECIFIC; + if (sysctl(name, nitems(name), NULL, &len, NULL, 0) == -1) { + syslog(LOG_WARNING, "sysctl linkmib estimate (%s): %m", + ifp->name); + if (ifp->specmib != NULL) { + ifp->specmib = NULL; + ifp->specmiblen = 0; + } + goto out; + } + if (len == 0) { + if (ifp->specmib != NULL) { + ifp->specmib = NULL; + ifp->specmiblen = 0; + } + goto out; + } + + if (ifp->specmiblen != len) { + if ((newmib = realloc(ifp->specmib, len)) == NULL) { + ifp->specmib = NULL; + ifp->specmiblen = 0; + goto out; + } + ifp->specmib = newmib; + ifp->specmiblen = len; + } + if (sysctl(name, nitems(name), ifp->specmib, &len, NULL, 0) == -1) { + syslog(LOG_WARNING, "sysctl linkmib (%s): %m", ifp->name); + if (ifp->specmib != NULL) { + ifp->specmib = NULL; + ifp->specmiblen = 0; + } + } + + out: + strlcpy(irr.ifr_name, ifp->name, sizeof(irr.ifr_name)); + irr.ifr_buffer.buffer = MIBIF_PRIV(ifp)->alias; + irr.ifr_buffer.length = sizeof(MIBIF_PRIV(ifp)->alias); + if (ioctl(mib_netsock, SIOCGIFDESCR, &irr) == -1) { + MIBIF_PRIV(ifp)->alias[0] = 0; + if (errno != ENOMSG) + syslog(LOG_WARNING, "SIOCGIFDESCR (%s): %m", ifp->name); + } else if (irr.ifr_buffer.buffer == NULL) { + MIBIF_PRIV(ifp)->alias[0] = 0; + syslog(LOG_WARNING, "SIOCGIFDESCR (%s): too long (%zu)", + ifp->name, irr.ifr_buffer.length); + } + ifp->mibtick = get_ticks(); + return (0); +} + +/* find first/next address for a given interface */ +struct mibifa * +mib_first_ififa(const struct mibif *ifp) +{ + struct mibifa *ifa; + + TAILQ_FOREACH(ifa, &mibifa_list, link) + if (ifp->index == ifa->ifindex) + return (ifa); + return (NULL); +} + +struct mibifa * +mib_next_ififa(struct mibifa *ifa0) +{ + struct mibifa *ifa; + + ifa = ifa0; + while ((ifa = TAILQ_NEXT(ifa, link)) != NULL) + if (ifa->ifindex == ifa0->ifindex) + return (ifa); + return (NULL); +} + +/* + * Allocate a new IFA + */ +static struct mibifa * +alloc_ifa(u_int ifindex, struct in_addr addr) +{ + struct mibifa *ifa; + uint32_t ha; + + if ((ifa = malloc(sizeof(struct mibifa))) == NULL) { + syslog(LOG_ERR, "ifa: %m"); + return (NULL); + } + ifa->inaddr = addr; + ifa->ifindex = ifindex; + + ha = ntohl(ifa->inaddr.s_addr); + ifa->index.len = 4; + ifa->index.subs[0] = (ha >> 24) & 0xff; + ifa->index.subs[1] = (ha >> 16) & 0xff; + ifa->index.subs[2] = (ha >> 8) & 0xff; + ifa->index.subs[3] = (ha >> 0) & 0xff; + + ifa->flags = 0; + ifa->inbcast.s_addr = 0; + ifa->inmask.s_addr = 0xffffffff; + + INSERT_OBJECT_OID(ifa, &mibifa_list); + + return (ifa); +} + +/* + * Delete an interface address + */ +static void +destroy_ifa(struct mibifa *ifa) +{ + TAILQ_REMOVE(&mibifa_list, ifa, link); + free(ifa); +} + + +/* + * Helper routine to extract the sockaddr structures from a routing + * socket message. + */ +void +mib_extract_addrs(int addrs, u_char *info, struct sockaddr **out) +{ + u_int i; + + for (i = 0; i < RTAX_MAX; i++) { + if ((addrs & (1 << i)) != 0) { + *out = (struct sockaddr *)(void *)info; + info += roundup((*out)->sa_len, sizeof(long)); + } else + *out = NULL; + out++; + } +} + +/* + * save the phys address of an interface. Handle receive address entries here. + */ +static void +get_physaddr(struct mibif *ifp, struct sockaddr_dl *sdl, u_char *ptr) +{ + u_char *np; + struct mibrcvaddr *rcv; + + if (sdl->sdl_alen == 0) { + /* no address */ + if (ifp->physaddrlen != 0) { + if ((rcv = mib_find_rcvaddr(ifp->index, ifp->physaddr, + ifp->physaddrlen)) != NULL) + mib_rcvaddr_delete(rcv); + free(ifp->physaddr); + ifp->physaddr = NULL; + ifp->physaddrlen = 0; + } + return; + } + + if (ifp->physaddrlen != sdl->sdl_alen) { + /* length changed */ + if (ifp->physaddrlen) { + /* delete olf receive address */ + if ((rcv = mib_find_rcvaddr(ifp->index, ifp->physaddr, + ifp->physaddrlen)) != NULL) + mib_rcvaddr_delete(rcv); + } + if ((np = realloc(ifp->physaddr, sdl->sdl_alen)) == NULL) { + free(ifp->physaddr); + ifp->physaddr = NULL; + ifp->physaddrlen = 0; + return; + } + ifp->physaddr = np; + ifp->physaddrlen = sdl->sdl_alen; + + } else if (memcmp(ifp->physaddr, ptr, ifp->physaddrlen) == 0) { + /* no change */ + return; + + } else { + /* address changed */ + + /* delete olf receive address */ + if ((rcv = mib_find_rcvaddr(ifp->index, ifp->physaddr, + ifp->physaddrlen)) != NULL) + mib_rcvaddr_delete(rcv); + } + + memcpy(ifp->physaddr, ptr, ifp->physaddrlen); + + /* make new receive address */ + if ((rcv = mib_rcvaddr_create(ifp, ifp->physaddr, ifp->physaddrlen)) != NULL) + rcv->flags |= MIBRCVADDR_HW; +} + +/* + * Free an interface + */ +static void +mibif_free(struct mibif *ifp) +{ + struct mibif *ifp1; + struct mibindexmap *map; + struct mibifa *ifa, *ifa1; + struct mibrcvaddr *rcv, *rcv1; + struct mibarp *at, *at1; + + if (ifp->xnotify != NULL) + (*ifp->xnotify)(ifp, MIBIF_NOTIFY_DESTROY, ifp->xnotify_data); + + (void)mib_ifstack_delete(ifp, NULL); + (void)mib_ifstack_delete(NULL, ifp); + + TAILQ_REMOVE(&mibif_list, ifp, link); + + /* if this was the fastest interface - recompute this */ + if (ifp->mib.ifmd_data.ifi_baudrate == mibif_maxspeed) { + mibif_maxspeed = ifp->mib.ifmd_data.ifi_baudrate; + TAILQ_FOREACH(ifp1, &mibif_list, link) + if (ifp1->mib.ifmd_data.ifi_baudrate > mibif_maxspeed) + mibif_maxspeed = + ifp1->mib.ifmd_data.ifi_baudrate; + mibif_reset_hc_timer(); + } + + free(ifp->private); + ifp->private = NULL; + free(ifp->physaddr); + ifp->physaddr = NULL; + free(ifp->specmib); + ifp->specmib = NULL; + + STAILQ_FOREACH(map, &mibindexmap_list, link) + if (map->mibif == ifp) { + map->mibif = NULL; + break; + } + + /* purge interface addresses */ + ifa = TAILQ_FIRST(&mibifa_list); + while (ifa != NULL) { + ifa1 = TAILQ_NEXT(ifa, link); + if (ifa->ifindex == ifp->index) + destroy_ifa(ifa); + ifa = ifa1; + } + + /* purge receive addresses */ + rcv = TAILQ_FIRST(&mibrcvaddr_list); + while (rcv != NULL) { + rcv1 = TAILQ_NEXT(rcv, link); + if (rcv->ifindex == ifp->index) + mib_rcvaddr_delete(rcv); + rcv = rcv1; + } + + /* purge ARP entries */ + at = TAILQ_FIRST(&mibarp_list); + while (at != NULL) { + at1 = TAILQ_NEXT(at, link); + if (at->index.subs[0] == ifp->index) + mib_arp_delete(at); + at = at1; + } + + free(ifp); + ifp = NULL; + mib_if_number--; + mib_iftable_last_change = this_tick; +} + +/* + * Create a new interface + */ +static struct mibif * +mibif_create(u_int sysindex, const char *name) +{ + struct mibif *ifp; + struct mibindexmap *map; + + if ((ifp = malloc(sizeof(*ifp))) == NULL) { + syslog(LOG_WARNING, "%s: %m", __func__); + return (NULL); + } + memset(ifp, 0, sizeof(*ifp)); + if ((ifp->private = malloc(sizeof(struct mibif_private))) == NULL) { + syslog(LOG_WARNING, "%s: %m", __func__); + free(ifp); + return (NULL); + } + memset(ifp->private, 0, sizeof(struct mibif_private)); + + ifp->sysindex = sysindex; + strlcpy(ifp->name, name, sizeof(ifp->name)); + strlcpy(ifp->descr, name, sizeof(ifp->descr)); + ifp->spec_oid = oid_zeroDotZero; + + map = NULL; + if (!mib_if_is_dyn(ifp->name)) { + /* non-dynamic. look whether we know the interface */ + STAILQ_FOREACH(map, &mibindexmap_list, link) + if (strcmp(map->name, ifp->name) == 0) { + ifp->index = map->ifindex; + map->mibif = ifp; + break; + } + /* assume it has a connector if it is not dynamic */ + ifp->has_connector = 1; + ifp->trap_enable = 1; + } + if (map == NULL) { + /* new interface - get new index */ + if (next_if_index > 0x7fffffff) + errx(1, "ifindex wrap"); + + if ((map = malloc(sizeof(*map))) == NULL) { + syslog(LOG_ERR, "ifmap: %m"); + free(ifp); + return (NULL); + } + map->ifindex = next_if_index++; + map->sysindex = ifp->sysindex; + strcpy(map->name, ifp->name); + map->mibif = ifp; + STAILQ_INSERT_TAIL(&mibindexmap_list, map, link); + } else { + /* re-instantiate. Introduce a counter discontinuity */ + ifp->counter_disc = get_ticks(); + } + ifp->index = map->ifindex; + ifp->mib.ifmd_data.ifi_link_state = LINK_STATE_UNKNOWN; + + INSERT_OBJECT_INT(ifp, &mibif_list); + mib_if_number++; + mib_iftable_last_change = this_tick; + + /* instantiate default ifStack entries */ + (void)mib_ifstack_create(ifp, NULL); + (void)mib_ifstack_create(NULL, ifp); + + return (ifp); +} + +/* + * Inform all interested parties about a new interface + */ +static void +notify_newif(struct mibif *ifp) +{ + struct newifreg *reg; + + TAILQ_FOREACH(reg, &newifreg_list, link) + if ((*reg->func)(ifp)) + return; +} + +/* + * This is called for new interfaces after we have fetched the interface + * MIB. If this is a broadcast interface try to guess the broadcast address + * depending on the interface type. + */ +static void +check_llbcast(struct mibif *ifp) +{ + static u_char ether_bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + struct mibrcvaddr *rcv; + + if (!(ifp->mib.ifmd_flags & IFF_BROADCAST)) + return; + + switch (ifp->mib.ifmd_data.ifi_type) { + + case IFT_ETHER: + case IFT_FDDI: + case IFT_ISO88025: + case IFT_L2VLAN: + if (mib_find_rcvaddr(ifp->index, ether_bcast, 6) == NULL && + (rcv = mib_rcvaddr_create(ifp, ether_bcast, 6)) != NULL) + rcv->flags |= MIBRCVADDR_BCAST; + break; + } +} + + +/* + * Retrieve the current interface list from the system. + */ +void +mib_refresh_iflist(void) +{ + struct mibif *ifp, *ifp1; + size_t len; + u_short idx; + int name[6]; + int count; + struct ifmibdata mib; + + TAILQ_FOREACH(ifp, &mibif_list, link) + ifp->flags &= ~MIBIF_FOUND; + + len = sizeof(count); + if (sysctlbyname("net.link.generic.system.ifcount", &count, &len, + NULL, 0) == -1) { + syslog(LOG_ERR, "ifcount: %m"); + return; + } + name[0] = CTL_NET; + name[1] = PF_LINK; + name[2] = NETLINK_GENERIC; + name[3] = IFMIB_IFDATA; + name[5] = IFDATA_GENERAL; + for (idx = 1; idx <= count; idx++) { + name[4] = idx; + len = sizeof(mib); + if (sysctl(name, nitems(name), &mib, &len, NULL, 0) == -1) { + if (errno == ENOENT) + continue; + syslog(LOG_ERR, "ifmib(%u): %m", idx); + return; + } + if ((ifp = mib_find_if_sys(idx)) != NULL) { + ifp->flags |= MIBIF_FOUND; + continue; + } + /* Unknown interface - create */ + if ((ifp = mibif_create(idx, mib.ifmd_name)) != NULL) { + ifp->flags |= MIBIF_FOUND; + (void)mib_fetch_ifmib(ifp); + check_llbcast(ifp); + notify_newif(ifp); + } + } + + /* + * Purge interfaces that disappeared + */ + ifp = TAILQ_FIRST(&mibif_list); + while (ifp != NULL) { + ifp1 = TAILQ_NEXT(ifp, link); + if (!(ifp->flags & MIBIF_FOUND)) + mibif_free(ifp); + ifp = ifp1; + } +} + +/* + * Find an interface address + */ +struct mibifa * +mib_find_ifa(struct in_addr addr) +{ + struct mibifa *ifa; + + TAILQ_FOREACH(ifa, &mibifa_list, link) + if (ifa->inaddr.s_addr == addr.s_addr) + return (ifa); + return (NULL); +} + +/* + * Process a new ARP entry + */ +static void +process_arp(const struct rt_msghdr *rtm, const struct sockaddr_dl *sdl, + const struct sockaddr_in *sa) +{ + struct mibif *ifp; + struct mibarp *at; + + /* IP arp table entry */ + if (sdl->sdl_alen == 0) + return; + if ((ifp = mib_find_if_sys(sdl->sdl_index)) == NULL) + return; + /* have a valid entry */ + if ((at = mib_find_arp(ifp, sa->sin_addr)) == NULL && + (at = mib_arp_create(ifp, sa->sin_addr, + sdl->sdl_data + sdl->sdl_nlen, sdl->sdl_alen)) == NULL) + return; + + if (rtm->rtm_rmx.rmx_expire == 0) + at->flags |= MIBARP_PERM; + else + at->flags &= ~MIBARP_PERM; + at->flags |= MIBARP_FOUND; +} + +/* + * Handle a routing socket message. + */ +static void +handle_rtmsg(struct rt_msghdr *rtm) +{ + struct sockaddr *addrs[RTAX_MAX]; + struct if_msghdr *ifm; + struct ifa_msghdr ifam, *ifamp; + struct ifma_msghdr *ifmam; +#ifdef RTM_IFANNOUNCE + struct if_announcemsghdr *ifan; +#endif + struct mibif *ifp; + struct sockaddr_dl *sdl; + struct sockaddr_in *sa; + struct mibifa *ifa; + struct mibrcvaddr *rcv; + u_char *ptr; + + if (rtm->rtm_version != RTM_VERSION) { + syslog(LOG_ERR, "Bogus RTM version %u", rtm->rtm_version); + return; + } + + switch (rtm->rtm_type) { + + case RTM_NEWADDR: + ifamp = (struct ifa_msghdr *)rtm; + memcpy(&ifam, ifamp, sizeof(ifam)); + mib_extract_addrs(ifam.ifam_addrs, (u_char *)(ifamp + 1), addrs); + if (addrs[RTAX_IFA] == NULL || addrs[RTAX_NETMASK] == NULL) + break; + + sa = (struct sockaddr_in *)(void *)addrs[RTAX_IFA]; + if ((ifa = mib_find_ifa(sa->sin_addr)) == NULL) { + /* unknown address */ + if ((ifp = mib_find_if_sys(ifam.ifam_index)) == NULL) { + syslog(LOG_WARNING, "RTM_NEWADDR for unknown " + "interface %u", ifam.ifam_index); + break; + } + if ((ifa = alloc_ifa(ifp->index, sa->sin_addr)) == NULL) + break; + } + sa = (struct sockaddr_in *)(void *)addrs[RTAX_NETMASK]; + ifa->inmask = sa->sin_addr; + + if (addrs[RTAX_BRD] != NULL) { + sa = (struct sockaddr_in *)(void *)addrs[RTAX_BRD]; + ifa->inbcast = sa->sin_addr; + } + ifa->flags |= MIBIFA_FOUND; + break; + + case RTM_DELADDR: + ifamp = (struct ifa_msghdr *)rtm; + memcpy(&ifam, ifamp, sizeof(ifam)); + mib_extract_addrs(ifam.ifam_addrs, (u_char *)(ifamp + 1), addrs); + if (addrs[RTAX_IFA] == NULL) + break; + + sa = (struct sockaddr_in *)(void *)addrs[RTAX_IFA]; + if ((ifa = mib_find_ifa(sa->sin_addr)) != NULL) { + ifa->flags |= MIBIFA_FOUND; + if (!(ifa->flags & MIBIFA_DESTROYED)) + destroy_ifa(ifa); + } + break; + + case RTM_NEWMADDR: + ifmam = (struct ifma_msghdr *)rtm; + mib_extract_addrs(ifmam->ifmam_addrs, (u_char *)(ifmam + 1), addrs); + if (addrs[RTAX_IFA] == NULL || + addrs[RTAX_IFA]->sa_family != AF_LINK) + break; + sdl = (struct sockaddr_dl *)(void *)addrs[RTAX_IFA]; + if ((rcv = mib_find_rcvaddr(sdl->sdl_index, + sdl->sdl_data + sdl->sdl_nlen, sdl->sdl_alen)) == NULL) { + /* unknown address */ + if ((ifp = mib_find_if_sys(sdl->sdl_index)) == NULL) { + syslog(LOG_WARNING, "RTM_NEWMADDR for unknown " + "interface %u", sdl->sdl_index); + break; + } + if ((rcv = mib_rcvaddr_create(ifp, + sdl->sdl_data + sdl->sdl_nlen, sdl->sdl_alen)) == NULL) + break; + rcv->flags |= MIBRCVADDR_VOLATILE; + } + rcv->flags |= MIBRCVADDR_FOUND; + break; + + case RTM_DELMADDR: + ifmam = (struct ifma_msghdr *)rtm; + mib_extract_addrs(ifmam->ifmam_addrs, (u_char *)(ifmam + 1), addrs); + if (addrs[RTAX_IFA] == NULL || + addrs[RTAX_IFA]->sa_family != AF_LINK) + break; + sdl = (struct sockaddr_dl *)(void *)addrs[RTAX_IFA]; + if ((rcv = mib_find_rcvaddr(sdl->sdl_index, + sdl->sdl_data + sdl->sdl_nlen, sdl->sdl_alen)) != NULL) + mib_rcvaddr_delete(rcv); + break; + + case RTM_IFINFO: + ifm = (struct if_msghdr *)(void *)rtm; + mib_extract_addrs(ifm->ifm_addrs, (u_char *)(ifm + 1), addrs); + if ((ifp = mib_find_if_sys(ifm->ifm_index)) == NULL) + break; + if (addrs[RTAX_IFP] != NULL && + addrs[RTAX_IFP]->sa_family == AF_LINK) { + sdl = (struct sockaddr_dl *)(void *)addrs[RTAX_IFP]; + ptr = sdl->sdl_data + sdl->sdl_nlen; + get_physaddr(ifp, sdl, ptr); + } + (void)mib_fetch_ifmib(ifp); + break; + +#ifdef RTM_IFANNOUNCE + case RTM_IFANNOUNCE: + ifan = (struct if_announcemsghdr *)rtm; + ifp = mib_find_if_sys(ifan->ifan_index); + + switch (ifan->ifan_what) { + + case IFAN_ARRIVAL: + if (ifp == NULL && (ifp = mibif_create(ifan->ifan_index, + ifan->ifan_name)) != NULL) { + (void)mib_fetch_ifmib(ifp); + check_llbcast(ifp); + notify_newif(ifp); + } + break; + + case IFAN_DEPARTURE: + if (ifp != NULL) + mibif_free(ifp); + break; + } + break; +#endif + case RTM_GET: + case RTM_ADD: + mib_extract_addrs(rtm->rtm_addrs, (u_char *)(rtm + 1), addrs); + if (rtm->rtm_flags & RTF_LLINFO) { + if (addrs[RTAX_DST] == NULL || + addrs[RTAX_GATEWAY] == NULL || + addrs[RTAX_DST]->sa_family != AF_INET || + addrs[RTAX_GATEWAY]->sa_family != AF_LINK) + break; + process_arp(rtm, + (struct sockaddr_dl *)(void *)addrs[RTAX_GATEWAY], + (struct sockaddr_in *)(void *)addrs[RTAX_DST]); + } else { + if (rtm->rtm_errno == 0 && (rtm->rtm_flags & RTF_UP)) + mib_sroute_process(rtm, addrs[RTAX_GATEWAY], + addrs[RTAX_DST], addrs[RTAX_NETMASK]); + } + break; + + case RTM_DELETE: + mib_extract_addrs(rtm->rtm_addrs, (u_char *)(rtm + 1), addrs); + + if (rtm->rtm_errno == 0 && (rtm->rtm_flags & RTF_UP)) + mib_sroute_process(rtm, addrs[RTAX_GATEWAY], + addrs[RTAX_DST], addrs[RTAX_NETMASK]); + break; + } +} + +/* + * send a routing message + */ +void +mib_send_rtmsg(struct rt_msghdr *rtm, struct sockaddr *gw, + struct sockaddr *dst, struct sockaddr *mask) +{ + size_t len; + struct rt_msghdr *msg; + char *cp; + ssize_t sent; + + len = sizeof(*rtm) + SA_SIZE(gw) + SA_SIZE(dst) + SA_SIZE(mask); + if ((msg = malloc(len)) == NULL) { + syslog(LOG_ERR, "%s: %m", __func__); + return; + } + cp = (char *)(msg + 1); + + memset(msg, 0, sizeof(*msg)); + msg->rtm_flags = 0; + msg->rtm_version = RTM_VERSION; + msg->rtm_addrs = RTA_DST | RTA_GATEWAY; + + memcpy(cp, dst, SA_SIZE(dst)); + cp += SA_SIZE(dst); + memcpy(cp, gw, SA_SIZE(gw)); + cp += SA_SIZE(gw); + if (mask != NULL) { + memcpy(cp, mask, SA_SIZE(mask)); + cp += SA_SIZE(mask); + msg->rtm_addrs |= RTA_NETMASK; + } + msg->rtm_msglen = cp - (char *)msg; + msg->rtm_type = RTM_GET; + if ((sent = write(route, msg, msg->rtm_msglen)) == -1) { + syslog(LOG_ERR, "%s: write: %m", __func__); + free(msg); + return; + } + if (sent != msg->rtm_msglen) { + syslog(LOG_ERR, "%s: short write", __func__); + free(msg); + return; + } + free(msg); +} + +/* + * Fetch the routing table via sysctl + */ +u_char * +mib_fetch_rtab(int af, int info, int arg, size_t *lenp) +{ + int name[6]; + u_char *buf, *newbuf; + + name[0] = CTL_NET; + name[1] = PF_ROUTE; + name[2] = 0; + name[3] = af; + name[4] = info; + name[5] = arg; + + *lenp = 0; + + /* initial estimate */ + if (sysctl(name, nitems(name), NULL, lenp, NULL, 0) == -1) { + syslog(LOG_ERR, "sysctl estimate (%d,%d,%d,%d,%d,%d): %m", + name[0], name[1], name[2], name[3], name[4], name[5]); + return (NULL); + } + if (*lenp == 0) + return (NULL); + + buf = NULL; + for (;;) { + if ((newbuf = realloc(buf, *lenp)) == NULL) { + syslog(LOG_ERR, "sysctl buffer: %m"); + free(buf); + return (NULL); + } + buf = newbuf; + + if (sysctl(name, nitems(name), buf, lenp, NULL, 0) == 0) + break; + + if (errno != ENOMEM) { + syslog(LOG_ERR, "sysctl get: %m"); + free(buf); + return (NULL); + } + *lenp += *lenp / 8 + 1; + } + + return (buf); +} + +/* + * Update the following info: interface, interface addresses, interface + * receive addresses, arp-table. + * This does not change the interface list itself. + */ +static void +update_ifa_info(void) +{ + u_char *buf, *next; + struct rt_msghdr *rtm; + struct mibifa *ifa, *ifa1; + struct mibrcvaddr *rcv, *rcv1; + size_t needed; + static const int infos[][3] = { + { 0, NET_RT_IFLIST, 0 }, +#ifdef NET_RT_IFMALIST + { AF_LINK, NET_RT_IFMALIST, 0 }, +#endif + }; + u_int i; + + TAILQ_FOREACH(ifa, &mibifa_list, link) + ifa->flags &= ~MIBIFA_FOUND; + TAILQ_FOREACH(rcv, &mibrcvaddr_list, link) + rcv->flags &= ~MIBRCVADDR_FOUND; + + for (i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { + if ((buf = mib_fetch_rtab(infos[i][0], infos[i][1], infos[i][2], + &needed)) == NULL) + continue; + + next = buf; + while (next < buf + needed) { + rtm = (struct rt_msghdr *)(void *)next; + next += rtm->rtm_msglen; + handle_rtmsg(rtm); + } + free(buf); + } + + /* + * Purge the address list of unused entries. These may happen for + * interface aliases that are on the same subnet. We don't receive + * routing socket messages for them. + */ + ifa = TAILQ_FIRST(&mibifa_list); + while (ifa != NULL) { + ifa1 = TAILQ_NEXT(ifa, link); + if (!(ifa->flags & MIBIFA_FOUND)) + destroy_ifa(ifa); + ifa = ifa1; + } + + rcv = TAILQ_FIRST(&mibrcvaddr_list); + while (rcv != NULL) { + rcv1 = TAILQ_NEXT(rcv, link); + if (!(rcv->flags & (MIBRCVADDR_FOUND | MIBRCVADDR_BCAST | + MIBRCVADDR_HW))) + mib_rcvaddr_delete(rcv); + rcv = rcv1; + } +} + +/* + * Update arp table + */ +void +mib_arp_update(void) +{ + struct mibarp *at, *at1; + size_t needed; + u_char *buf, *next; + struct rt_msghdr *rtm; + + if (in_update_arp) + return; /* Aaargh */ + in_update_arp = 1; + + TAILQ_FOREACH(at, &mibarp_list, link) + at->flags &= ~MIBARP_FOUND; + + if ((buf = mib_fetch_rtab(AF_INET, NET_RT_FLAGS, 0, &needed)) == NULL) { + in_update_arp = 0; + return; + } + + next = buf; + while (next < buf + needed) { + rtm = (struct rt_msghdr *)(void *)next; + next += rtm->rtm_msglen; + handle_rtmsg(rtm); + } + free(buf); + + at = TAILQ_FIRST(&mibarp_list); + while (at != NULL) { + at1 = TAILQ_NEXT(at, link); + if (!(at->flags & MIBARP_FOUND)) + mib_arp_delete(at); + at = at1; + } + mibarpticks = get_ticks(); + in_update_arp = 0; +} + + +/* + * Input on the routing socket. + */ +static void +route_input(int fd, void *udata __unused) +{ + u_char buf[1024 * 16]; + ssize_t n; + struct rt_msghdr *rtm; + + if ((n = read(fd, buf, sizeof(buf))) == -1) + err(1, "read(rt_socket)"); + + if (n == 0) + errx(1, "EOF on rt_socket"); + + rtm = (struct rt_msghdr *)(void *)buf; + if ((size_t)n != rtm->rtm_msglen) + errx(1, "n=%zu, rtm_msglen=%u", (size_t)n, rtm->rtm_msglen); + + handle_rtmsg(rtm); +} + +/* + * execute and SIOCAIFADDR + */ +static int +siocaifaddr(char *ifname, struct in_addr addr, struct in_addr mask, + struct in_addr bcast) +{ + struct ifaliasreq addreq; + struct sockaddr_in *sa; + + memset(&addreq, 0, sizeof(addreq)); + strlcpy(addreq.ifra_name, ifname, sizeof(addreq.ifra_name)); + + sa = (struct sockaddr_in *)(void *)&addreq.ifra_addr; + sa->sin_family = AF_INET; + sa->sin_len = sizeof(*sa); + sa->sin_addr = addr; + + sa = (struct sockaddr_in *)(void *)&addreq.ifra_mask; + sa->sin_family = AF_INET; + sa->sin_len = sizeof(*sa); + sa->sin_addr = mask; + + sa = (struct sockaddr_in *)(void *)&addreq.ifra_broadaddr; + sa->sin_family = AF_INET; + sa->sin_len = sizeof(*sa); + sa->sin_addr = bcast; + + return (ioctl(mib_netsock, SIOCAIFADDR, &addreq)); +} + +/* + * Exececute a SIOCDIFADDR + */ +static int +siocdifaddr(const char *ifname, struct in_addr addr) +{ + struct ifreq delreq; + struct sockaddr_in *sa; + + memset(&delreq, 0, sizeof(delreq)); + strlcpy(delreq.ifr_name, ifname, sizeof(delreq.ifr_name)); + sa = (struct sockaddr_in *)(void *)&delreq.ifr_addr; + sa->sin_family = AF_INET; + sa->sin_len = sizeof(*sa); + sa->sin_addr = addr; + + return (ioctl(mib_netsock, SIOCDIFADDR, &delreq)); +} + +/* + * Verify an interface address without fetching the entire list + */ +static int +verify_ifa(const char *name, struct mibifa *ifa) +{ + struct ifreq req; + struct sockaddr_in *sa; + + memset(&req, 0, sizeof(req)); + strlcpy(req.ifr_name, name, sizeof(req.ifr_name)); + sa = (struct sockaddr_in *)(void *)&req.ifr_addr; + sa->sin_family = AF_INET; + sa->sin_len = sizeof(*sa); + sa->sin_addr = ifa->inaddr; + + if (ioctl(mib_netsock, SIOCGIFADDR, &req) == -1) + return (-1); + if (ifa->inaddr.s_addr != sa->sin_addr.s_addr) { + syslog(LOG_ERR, "%s: address mismatch", __func__); + return (-1); + } + + if (ioctl(mib_netsock, SIOCGIFNETMASK, &req) == -1) + return (-1); + if (ifa->inmask.s_addr != sa->sin_addr.s_addr) { + syslog(LOG_ERR, "%s: netmask mismatch", __func__); + return (-1); + } + return (0); +} + +/* + * Restore a deleted interface address. Don't wait for the routing socket + * to update us. + */ +void +mib_undestroy_ifa(struct mibifa *ifa) +{ + struct mibif *ifp; + + if ((ifp = mib_find_if(ifa->ifindex)) == NULL) + /* keep it destroyed */ + return; + + if (siocaifaddr(ifp->name, ifa->inaddr, ifa->inmask, ifa->inbcast)) + /* keep it destroyed */ + return; + + ifa->flags &= ~MIBIFA_DESTROYED; +} + +/* + * Destroy an interface address + */ +int +mib_destroy_ifa(struct mibifa *ifa) +{ + struct mibif *ifp; + + if ((ifp = mib_find_if(ifa->ifindex)) == NULL) { + /* ups. */ + mib_iflist_bad = 1; + return (-1); + } + if (siocdifaddr(ifp->name, ifa->inaddr)) { + /* ups. */ + syslog(LOG_ERR, "SIOCDIFADDR: %m"); + mib_iflist_bad = 1; + return (-1); + } + ifa->flags |= MIBIFA_DESTROYED; + return (0); +} + +/* + * Rollback the modification of an address. Don't bother to wait for + * the routing socket. + */ +void +mib_unmodify_ifa(struct mibifa *ifa) +{ + struct mibif *ifp; + + if ((ifp = mib_find_if(ifa->ifindex)) == NULL) { + /* ups. */ + mib_iflist_bad = 1; + return; + } + + if (siocaifaddr(ifp->name, ifa->inaddr, ifa->inmask, ifa->inbcast)) { + /* ups. */ + mib_iflist_bad = 1; + return; + } +} + +/* + * Modify an IFA. + */ +int +mib_modify_ifa(struct mibifa *ifa) +{ + struct mibif *ifp; + + if ((ifp = mib_find_if(ifa->ifindex)) == NULL) { + /* ups. */ + mib_iflist_bad = 1; + return (-1); + } + + if (siocaifaddr(ifp->name, ifa->inaddr, ifa->inmask, ifa->inbcast)) { + /* ups. */ + mib_iflist_bad = 1; + return (-1); + } + + if (verify_ifa(ifp->name, ifa)) { + /* ups. */ + mib_iflist_bad = 1; + return (-1); + } + + return (0); +} + +/* + * Destroy a freshly created interface address. Don't bother to wait for + * the routing socket. + */ +void +mib_uncreate_ifa(struct mibifa *ifa) +{ + struct mibif *ifp; + + if ((ifp = mib_find_if(ifa->ifindex)) == NULL) { + /* ups. */ + mib_iflist_bad = 1; + return; + } + if (siocdifaddr(ifp->name, ifa->inaddr)) { + /* ups. */ + mib_iflist_bad = 1; + return; + } + + destroy_ifa(ifa); +} + +/* + * Create a new ifa and verify it + */ +struct mibifa * +mib_create_ifa(u_int ifindex, struct in_addr addr, struct in_addr mask, + struct in_addr bcast) +{ + struct mibif *ifp; + struct mibifa *ifa; + + if ((ifp = mib_find_if(ifindex)) == NULL) + return (NULL); + if ((ifa = alloc_ifa(ifindex, addr)) == NULL) + return (NULL); + ifa->inmask = mask; + ifa->inbcast = bcast; + + if (siocaifaddr(ifp->name, ifa->inaddr, ifa->inmask, ifa->inbcast)) { + syslog(LOG_ERR, "%s: %m", __func__); + destroy_ifa(ifa); + return (NULL); + } + if (verify_ifa(ifp->name, ifa)) { + destroy_ifa(ifa); + return (NULL); + } + return (ifa); +} + +/* + * Get all cloning interfaces and make them dynamic. + * Hah! Whe should probably do this on a periodic basis (XXX). + */ +static void +get_cloners(void) +{ + struct if_clonereq req; + char *buf, *cp; + int i; + + memset(&req, 0, sizeof(req)); + if (ioctl(mib_netsock, SIOCIFGCLONERS, &req) == -1) { + syslog(LOG_ERR, "get cloners: %m"); + return; + } + if ((buf = malloc(req.ifcr_total * IFNAMSIZ)) == NULL) { + syslog(LOG_ERR, "%m"); + return; + } + req.ifcr_count = req.ifcr_total; + req.ifcr_buffer = buf; + if (ioctl(mib_netsock, SIOCIFGCLONERS, &req) == -1) { + syslog(LOG_ERR, "get cloners: %m"); + free(buf); + return; + } + for (cp = buf, i = 0; i < req.ifcr_total; i++, cp += IFNAMSIZ) + mib_if_set_dyn(cp); + free(buf); +} + +/* + * Idle function + */ +static void +mibII_idle(void *arg __unused) +{ + struct mibifa *ifa; + + if (mib_iflist_bad) { + TAILQ_FOREACH(ifa, &mibifa_list, link) + ifa->flags &= ~MIBIFA_DESTROYED; + + /* assume, that all cloning interfaces are dynamic */ + get_cloners(); + + mib_refresh_iflist(); + update_ifa_info(); + mib_arp_update(); + mib_iflist_bad = 0; + } + + mib_arp_update(); +} + + +/* + * Start the module + */ +static void +mibII_start(void) +{ + if ((route_fd = fd_select(route, route_input, NULL, module)) == NULL) { + syslog(LOG_ERR, "fd_select(route): %m"); + return; + } + mib_refresh_iflist(); + update_ifa_info(); + mib_arp_update(); + (void)mib_fetch_route(); + mib_iftable_last_change = 0; + mib_ifstack_last_change = 0; + + ifmib_reg = or_register(&oid_ifMIB, + "The MIB module to describe generic objects for network interface" + " sub-layers.", module); + + ipmib_reg = or_register(&oid_ipMIB, + "The MIB module for managing IP and ICMP implementations, but " + "excluding their management of IP routes.", module); + + tcpmib_reg = or_register(&oid_tcpMIB, + "The MIB module for managing TCP implementations.", module); + + udpmib_reg = or_register(&oid_udpMIB, + "The MIB module for managing UDP implementations.", module); + + ipForward_reg = or_register(&oid_ipForward, + "The MIB module for the display of CIDR multipath IP Routes.", + module); + + mibII_poll_timer = NULL; + mibII_poll_ticks = MIBII_POLL_TICKS; + mibif_restart_mibII_poll_timer(); +} + +/* + * Initialize the module + */ +static int +mibII_init(struct lmodule *mod, int argc __unused, char *argv[] __unused) +{ + size_t len; + + module = mod; + + len = sizeof(clockinfo); + if (sysctlbyname("kern.clockrate", &clockinfo, &len, NULL, 0) == -1) { + syslog(LOG_ERR, "kern.clockrate: %m"); + return (-1); + } + if (len != sizeof(clockinfo)) { + syslog(LOG_ERR, "kern.clockrate: wrong size"); + return (-1); + } + + if ((route = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC)) == -1) { + syslog(LOG_ERR, "PF_ROUTE: %m"); + return (-1); + } + + if ((mib_netsock = socket(PF_INET, SOCK_DGRAM, 0)) == -1) { + syslog(LOG_ERR, "PF_INET: %m"); + (void)close(route); + return (-1); + } + (void)shutdown(mib_netsock, SHUT_RDWR); + + /* assume, that all cloning interfaces are dynamic */ + get_cloners(); + + return (0); +} + +static int +mibII_fini(void) +{ + if (mibII_poll_timer != NULL ) { + timer_stop(mibII_poll_timer); + mibII_poll_timer = NULL; + } + + if (route_fd != NULL) + fd_deselect(route_fd); + if (route != -1) + (void)close(route); + if (mib_netsock != -1) + (void)close(mib_netsock); + /* XXX free memory */ + + or_unregister(ipForward_reg); + or_unregister(udpmib_reg); + or_unregister(tcpmib_reg); + or_unregister(ipmib_reg); + or_unregister(ifmib_reg); + + return (0); +} + +static void +mibII_loading(const struct lmodule *mod, int loaded) +{ + struct mibif *ifp; + + if (loaded == 1) + return; + + TAILQ_FOREACH(ifp, &mibif_list, link) + if (ifp->xnotify_mod == mod) { + ifp->xnotify_mod = NULL; + ifp->xnotify_data = NULL; + ifp->xnotify = NULL; + } + + mib_unregister_newif(mod); +} + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-variable-declarations" +const struct snmp_module config = { + "This module implements the interface and ip groups.", + mibII_init, + mibII_fini, + NULL, /* idle */ + NULL, /* dump */ + NULL, /* config */ + mibII_start, + NULL, + mibII_ctree, + mibII_CTREE_SIZE, + mibII_loading +}; +#pragma GCC diagnostic push + +/* + * Should have a list of these attached to each interface. + */ +void * +mibif_notify(struct mibif *ifp, const struct lmodule *mod, + mibif_notify_f func, void *data) +{ + ifp->xnotify = func; + ifp->xnotify_data = data; + ifp->xnotify_mod = mod; + + return (ifp); +} + +void +mibif_unnotify(void *arg) +{ + struct mibif *ifp = arg; + + ifp->xnotify = NULL; + ifp->xnotify_data = NULL; + ifp->xnotify_mod = NULL; +} Property changes on: vendor/bsnmp/1.13/snmp_mibII/mibII.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/mibII.h =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/mibII.h (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/mibII.h (revision 336778) @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmp_mibII/mibII.h,v 1.16 2006/02/14 09:04:19 brandt_h Exp $ + * + * Implementation of the interfaces and IP groups of MIB-II. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "asn1.h" +#include "snmp.h" +#include "snmpmod.h" +#include "snmp_mibII.h" +#include "mibII_tree.h" + +/* maximum size of the interface alias */ +#define MIBIF_ALIAS_SIZE (64 + 1) + +/* + * Interface list and flags. + */ +TAILQ_HEAD(mibif_list, mibif); +enum { + MIBIF_FOUND = 0x0001, + MIBIF_HIGHSPEED = 0x0002, + MIBIF_VERYHIGHSPEED = 0x0004, +}; + +/* + * Private mibif data - hang off from the mibif. + */ +struct mibif_private { + uint64_t hc_inoctets; + uint64_t hc_outoctets; + uint64_t hc_omcasts; + uint64_t hc_opackets; + uint64_t hc_imcasts; + uint64_t hc_ipackets; + + /* this should be made public */ + char alias[MIBIF_ALIAS_SIZE]; +}; +#define MIBIF_PRIV(IFP) ((struct mibif_private *)((IFP)->private)) + +/* + * Interface addresses. + */ +TAILQ_HEAD(mibifa_list, mibifa); +enum { + MIBIFA_FOUND = 0x0001, + MIBIFA_DESTROYED = 0x0002, +}; + +/* + * Receive addresses + */ +TAILQ_HEAD(mibrcvaddr_list, mibrcvaddr); +enum { + MIBRCVADDR_FOUND = 0x00010000, +}; + +/* + * Interface index mapping. The problem here is, that if the same interface + * is reinstantiated (for examble by unloading and loading the hardware driver) + * we must use the same index for this interface. For dynamic interfaces + * (clip, lane) we must use a fresh index, each time a new interface is created. + * To differentiate between these types of interfaces we use the following table + * which contains an entry for each dynamic interface type. All other interface + * types are supposed to be static. The mibindexmap contains an entry for + * all interfaces. The mibif pointer is NULL, if the interface doesn't exist + * anymore. + */ +struct mibdynif { + SLIST_ENTRY(mibdynif) link; + char name[IFNAMSIZ]; +}; +SLIST_HEAD(mibdynif_list, mibdynif); + +struct mibindexmap { + STAILQ_ENTRY(mibindexmap) link; + u_short sysindex; + u_int ifindex; + struct mibif *mibif; /* may be NULL */ + char name[IFNAMSIZ]; +}; +STAILQ_HEAD(mibindexmap_list, mibindexmap); + +/* + * Interface stacking. The generic code cannot know how the interfaces stack. + * For this reason it instantiates only the x.0 and 0.x table elements. All + * others have to be instantiated by the interface specific modules. + * The table is read-only. + */ +struct mibifstack { + TAILQ_ENTRY(mibifstack) link; + struct asn_oid index; +}; +TAILQ_HEAD(mibifstack_list, mibifstack); + +/* + * NetToMediaTable (ArpTable) + */ +struct mibarp { + TAILQ_ENTRY(mibarp) link; + struct asn_oid index; /* contains both the ifindex and addr */ + u_char phys[128]; /* the physical address */ + u_int physlen; /* and its length */ + u_int flags; +}; +TAILQ_HEAD(mibarp_list, mibarp); +enum { + MIBARP_FOUND = 0x00010000, + MIBARP_PERM = 0x00000001, +}; + +/* + * New if registrations + */ +struct newifreg { + TAILQ_ENTRY(newifreg) link; + const struct lmodule *mod; + int (*func)(struct mibif *); +}; +TAILQ_HEAD(newifreg_list, newifreg); + +/* list of all IP addresses */ +extern struct mibifa_list mibifa_list; + +/* list of all interfaces */ +extern struct mibif_list mibif_list; + +/* list of dynamic interface names */ +extern struct mibdynif_list mibdynif_list; + +/* list of all interface index mappings */ +extern struct mibindexmap_list mibindexmap_list; + +/* list of all stacking entries */ +extern struct mibifstack_list mibifstack_list; + +/* list of all receive addresses */ +extern struct mibrcvaddr_list mibrcvaddr_list; + +/* list of all NetToMedia entries */ +extern struct mibarp_list mibarp_list; + +/* number of interfaces */ +extern int32_t mib_if_number; + +/* last change of interface table */ +extern uint64_t mib_iftable_last_change; + +/* last change of stack table */ +extern uint64_t mib_ifstack_last_change; + +/* if this is set, one of our lists may be bad. refresh them when idle */ +extern int mib_iflist_bad; + +/* last time refreshed */ +extern uint64_t mibarpticks; + +/* info on system clocks */ +extern struct clockinfo clockinfo; + +/* baud rate of fastest interface */ +extern uint64_t mibif_maxspeed; + +/* user-forced update interval */ +extern u_int mibif_force_hc_update_interval; + +/* current update interval */ +extern u_int mibif_hc_update_interval; + +/* re-compute update interval */ +void mibif_reset_hc_timer(void); + +/* interfaces' data poll interval */ +extern u_int mibII_poll_ticks; + +/* restart the data poll timer */ +void mibif_restart_mibII_poll_timer(void); + +#define MIBII_POLL_TICKS 100 + +/* get interfaces and interface addresses. */ +void mib_fetch_interfaces(void); + +/* check whether this interface(type) is dynamic */ +int mib_if_is_dyn(const char *name); + +/* destroy an interface address */ +int mib_destroy_ifa(struct mibifa *); + +/* restituate a deleted interface address */ +void mib_undestroy_ifa(struct mibifa *); + +/* change interface address */ +int mib_modify_ifa(struct mibifa *); + +/* undo if address modification */ +void mib_unmodify_ifa(struct mibifa *); + +/* create an interface address */ +struct mibifa * mib_create_ifa(u_int ifindex, struct in_addr addr, struct in_addr mask, struct in_addr bcast); + +/* delete a freshly created address */ +void mib_uncreate_ifa(struct mibifa *); + +/* create/delete arp entries */ +struct mibarp *mib_arp_create(const struct mibif *, struct in_addr, const u_char *, size_t); +void mib_arp_delete(struct mibarp *); + +/* find arp entry */ +struct mibarp *mib_find_arp(const struct mibif *, struct in_addr); + +/* update arp table */ +void mib_arp_update(void); + +/* fetch routing table */ +u_char *mib_fetch_rtab(int af, int info, int arg, size_t *lenp); + +/* process routing message */ +void mib_sroute_process(struct rt_msghdr *, struct sockaddr *, + struct sockaddr *, struct sockaddr *); + +/* send a routing message */ +void mib_send_rtmsg(struct rt_msghdr *, struct sockaddr *, + struct sockaddr *, struct sockaddr *); + +/* extract addresses from routing message */ +void mib_extract_addrs(int, u_char *, struct sockaddr **); + +/* fetch routing table */ +int mib_fetch_route(void); Property changes on: vendor/bsnmp/1.13/snmp_mibII/mibII.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/mibII_begemot.c =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/mibII_begemot.c (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/mibII_begemot.c (revision 336778) @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2006 + * Hartmut Brandt. + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmp_mibII/mibII_begemot.c,v 1.1 2006/02/14 09:04:19 brandt_h Exp $ + * + * Private MIB. + */ +#include "mibII.h" +#include "mibII_oid.h" + +/* + * Scalars + */ +int +op_begemot_mibII(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int idx __unused, enum snmp_op op) +{ + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + goto get; + + case SNMP_OP_SET: + switch (value->var.subs[sub - 1]) { + + case LEAF_begemotIfMaxspeed: + case LEAF_begemotIfPoll: + return (SNMP_ERR_NOT_WRITEABLE); + + case LEAF_begemotIfForcePoll: + ctx->scratch->int1 = mibif_force_hc_update_interval; + mibif_force_hc_update_interval = value->v.uint32; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotIfDataPoll: + ctx->scratch->int1 = mibII_poll_ticks; + mibII_poll_ticks = value->v.uint32; + return (SNMP_ERR_NOERROR); + } + abort(); + + case SNMP_OP_ROLLBACK: + switch (value->var.subs[sub - 1]) { + + case LEAF_begemotIfForcePoll: + mibif_force_hc_update_interval = ctx->scratch->int1; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotIfDataPoll: + mibII_poll_ticks = ctx->scratch->int1; + return (SNMP_ERR_NOERROR); + } + abort(); + + case SNMP_OP_COMMIT: + switch (value->var.subs[sub - 1]) { + + case LEAF_begemotIfForcePoll: + mibif_force_hc_update_interval = ctx->scratch->int1; + mibif_reset_hc_timer(); + return (SNMP_ERR_NOERROR); + + case LEAF_begemotIfDataPoll: + mibif_restart_mibII_poll_timer(); + return (SNMP_ERR_NOERROR); + } + abort(); + } + abort(); + + get: + + switch (value->var.subs[sub - 1]) { + + case LEAF_begemotIfMaxspeed: + value->v.counter64 = mibif_maxspeed; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotIfPoll: + value->v.uint32 = mibif_hc_update_interval; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotIfForcePoll: + value->v.uint32 = mibif_force_hc_update_interval; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotIfDataPoll: + value->v.uint32 = mibII_poll_ticks; + return (SNMP_ERR_NOERROR); + } + abort(); +} Property changes on: vendor/bsnmp/1.13/snmp_mibII/mibII_begemot.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/mibII_ifmib.c =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/mibII_ifmib.c (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/mibII_ifmib.c (revision 336778) @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmp_mibII/mibII_ifmib.c,v 1.9 2004/08/06 08:47:00 brandt Exp $ + * + * Interfaces group. + */ +#include "mibII.h" +#include "mibII_oid.h" + +/* + * Scalars + */ +int +op_ifmib(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int idx __unused, enum snmp_op op) +{ + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + break; + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + abort(); + } + + switch (value->var.subs[sub - 1]) { + + case LEAF_ifTableLastChange: + if (mib_iftable_last_change > start_tick) + value->v.uint32 = mib_iftable_last_change - start_tick; + else + value->v.uint32 = 0; + break; + + case LEAF_ifStackLastChange: + if (mib_ifstack_last_change > start_tick) + value->v.uint32 = mib_ifstack_last_change - start_tick; + else + value->v.uint32 = 0; + break; + } + return (SNMP_ERR_NOERROR); +} Property changes on: vendor/bsnmp/1.13/snmp_mibII/mibII_ifmib.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/mibII_ifstack.c =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/mibII_ifstack.c (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/mibII_ifstack.c (revision 336778) @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmp_mibII/mibII_ifstack.c,v 1.7 2004/08/06 08:47:00 brandt Exp $ + * + * ifStackTable. Read-only. + */ +#include "mibII.h" + +int +mib_ifstack_create(const struct mibif *lower, const struct mibif *upper) +{ + struct mibifstack *stack; + + if ((stack = malloc(sizeof(*stack))) == NULL) + return (-1); + + stack->index.len = 2; + stack->index.subs[0] = upper ? upper->index : 0; + stack->index.subs[1] = lower ? lower->index : 0; + + INSERT_OBJECT_OID(stack, &mibifstack_list); + + mib_ifstack_last_change = get_ticks(); + + return (0); +} + +void +mib_ifstack_delete(const struct mibif *lower, const struct mibif *upper) +{ + struct mibifstack *stack; + + TAILQ_FOREACH(stack, &mibifstack_list, link) + if (stack->index.subs[0] == (upper ? upper->index : 0) && + stack->index.subs[1] == (lower ? lower->index : 0)) { + TAILQ_REMOVE(&mibifstack_list, stack, link); + free(stack); + mib_ifstack_last_change = get_ticks(); + return; + } +} + +int +op_ifstack(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + struct mibifstack *stack; + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((stack = NEXT_OBJECT_OID(&mibifstack_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &stack->index); + break; + + case SNMP_OP_GET: + if ((stack = FIND_OBJECT_OID(&mibifstack_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if ((stack = FIND_OBJECT_OID(&mibifstack_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NO_CREATION); + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + abort(); + } + + switch (value->var.subs[sub - 1]) { + + case LEAF_ifStackStatus: + value->v.integer = 1; + break; + } + return (SNMP_ERR_NOERROR); +} Property changes on: vendor/bsnmp/1.13/snmp_mibII/mibII_ifstack.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/mibII_interfaces.c =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/mibII_interfaces.c (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/mibII_interfaces.c (revision 336778) @@ -0,0 +1,542 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmp_mibII/mibII_interfaces.c,v 1.17 2006/02/14 09:04:19 brandt_h Exp $ + * + * Interfaces group. + */ +#include "mibII.h" +#include "mibII_oid.h" + +/* + * This structure catches all changes to a interface entry + */ +struct ifchange { + struct snmp_dependency dep; + + u_int ifindex; + + uint32_t set; + int promisc; + int admin; + int traps; + + uint32_t rb; + int rb_flags; + int rb_traps; +}; +#define IFC_PROMISC 0x0001 +#define IFC_ADMIN 0x0002 +#define IFC_TRAPS 0x0004 +#define IFRB_FLAGS 0x0001 +#define IFRB_TRAPS 0x0002 + +static const struct asn_oid + oid_ifTable = OIDX_ifTable; + +/* + * This function handles all changes to the interface table and interface + * extension table. + */ +static int +ifchange_func(struct snmp_context *ctx __unused, struct snmp_dependency *dep, + enum snmp_depop op) +{ + struct ifchange *ifc = (struct ifchange *)dep; + struct mibif *ifp; + struct ifreq ifr, ifr1; + + if ((ifp = mib_find_if(ifc->ifindex)) == NULL) + return (SNMP_ERR_NO_CREATION); + + switch (op) { + + case SNMP_DEPOP_COMMIT: + strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); + if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr) == -1) { + syslog(LOG_ERR, "GIFFLAGS(%s): %m", ifp->name); + return (SNMP_ERR_GENERR); + } + if (ifc->set & IFC_PROMISC) { + ifr.ifr_flags &= ~IFF_PROMISC; + if (ifc->promisc) + ifr.ifr_flags |= IFF_PROMISC; + ifc->rb |= IFRB_FLAGS; + } + if (ifc->set & IFC_ADMIN) { + ifr.ifr_flags &= ~IFF_UP; + if (ifc->admin) + ifr.ifr_flags |= IFF_UP; + ifc->rb |= IFRB_FLAGS; + } + if (ifc->rb & IFRB_FLAGS) { + strlcpy(ifr1.ifr_name, ifp->name, sizeof(ifr1.ifr_name)); + if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr1) == -1) { + syslog(LOG_ERR, "GIFFLAGS(%s): %m", ifp->name); + return (SNMP_ERR_GENERR); + } + ifc->rb_flags = ifr1.ifr_flags; + if (ioctl(mib_netsock, SIOCSIFFLAGS, &ifr) == -1) { + syslog(LOG_ERR, "SIFFLAGS(%s): %m", ifp->name); + return (SNMP_ERR_GENERR); + } + (void)mib_fetch_ifmib(ifp); + } + if (ifc->set & IFC_TRAPS) { + ifc->rb |= IFRB_TRAPS; + ifc->rb_traps = ifp->trap_enable; + ifp->trap_enable = ifc->traps; + } + return (SNMP_ERR_NOERROR); + + case SNMP_DEPOP_ROLLBACK: + if (ifc->rb & IFRB_FLAGS) { + strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); + ifr.ifr_flags = ifc->rb_flags; + if (ioctl(mib_netsock, SIOCSIFFLAGS, &ifr) == -1) { + syslog(LOG_ERR, "SIFFLAGS(%s): %m", ifp->name); + return (SNMP_ERR_UNDO_FAILED); + } + (void)mib_fetch_ifmib(ifp); + } + if (ifc->rb & IFRB_TRAPS) + ifp->trap_enable = ifc->rb_traps; + return (SNMP_ERR_NOERROR); + + case SNMP_DEPOP_FINISH: + return (SNMP_ERR_NOERROR); + + } + abort(); +} + +/* + * Return difference to daemon start time in ticks truncated to a + * 32-bit value. If the timeval is 0 then return 0. + */ +static uint32_t +ticks_get_timeval(struct timeval *tv) +{ + uint64_t v; + + if (tv->tv_sec != 0 || tv->tv_usec != 0) { + v = 100ULL * tv->tv_sec + tv->tv_usec / 10000ULL; + if (v > start_tick) + return (v - start_tick); + } + return (0); +} + +/* + * Scalars + */ +int +op_interfaces(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int idx __unused, enum snmp_op op) +{ + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + break; + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + abort(); + } + + switch (value->var.subs[sub - 1]) { + + case LEAF_ifNumber: + value->v.integer = mib_if_number; + break; + } + return (SNMP_ERR_NOERROR); +} + +/* + * Iftable entry + */ +int +op_ifentry(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + struct mibif *ifp = NULL; + int ret; + struct ifchange *ifc; + struct asn_oid idx; + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((ifp = NEXT_OBJECT_INT(&mibif_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + value->var.len = sub + 1; + value->var.subs[sub] = ifp->index; + break; + + case SNMP_OP_GET: + if (value->var.len - sub != 1) + return (SNMP_ERR_NOSUCHNAME); + if ((ifp = mib_find_if(value->var.subs[sub])) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if (value->var.len - sub != 1) + return (SNMP_ERR_NO_CREATION); + if ((ifp = mib_find_if(value->var.subs[sub])) == NULL) + return (SNMP_ERR_NO_CREATION); + if (value->var.subs[sub - 1] != LEAF_ifAdminStatus) + return (SNMP_ERR_NOT_WRITEABLE); + + idx.len = 1; + idx.subs[0] = ifp->index; + + if (value->v.integer != 1 && value->v.integer != 2) + return (SNMP_ERR_WRONG_VALUE); + + if ((ifc = (struct ifchange *)snmp_dep_lookup(ctx, + &oid_ifTable, &idx, sizeof(*ifc), ifchange_func)) == NULL) + return (SNMP_ERR_RES_UNAVAIL); + ifc->ifindex = ifp->index; + + if (ifc->set & IFC_ADMIN) + return (SNMP_ERR_INCONS_VALUE); + ifc->set |= IFC_ADMIN; + ifc->admin = (value->v.integer == 1) ? 1 : 0; + + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + } + + if (ifp->mibtick < this_tick) + (void)mib_fetch_ifmib(ifp); + + ret = SNMP_ERR_NOERROR; + switch (value->var.subs[sub - 1]) { + + case LEAF_ifIndex: + value->v.integer = ifp->index; + break; + + case LEAF_ifDescr: + ret = string_get(value, ifp->descr, -1); + break; + + case LEAF_ifType: + value->v.integer = ifp->mib.ifmd_data.ifi_type; + break; + + case LEAF_ifMtu: + value->v.integer = ifp->mib.ifmd_data.ifi_mtu; + break; + + case LEAF_ifSpeed: + value->v.integer = ifp->mib.ifmd_data.ifi_baudrate; + break; + + case LEAF_ifPhysAddress: + ret = string_get(value, ifp->physaddr, + ifp->physaddrlen); + break; + + case LEAF_ifAdminStatus: + value->v.integer = + (ifp->mib.ifmd_flags & IFF_UP) ? 1 : 2; + break; + + case LEAF_ifOperStatus: + /* + * According to RFC 2863 the state should be Up if the + * interface is ready to transmit packets. We takes this to + * mean that the interface should be running and should have + * a carrier. If it is running and has no carrier we interpret + * this as 'waiting for an external event' (plugging in the + * cable) and hence return 'dormant'. + */ + if (ifp->mib.ifmd_flags & IFF_RUNNING) { + if (ifp->mib.ifmd_data.ifi_link_state != LINK_STATE_UP) + value->v.integer = 5; /* state dormant */ + else + value->v.integer = 1; /* state up */ + } else + value->v.integer = 2; /* state down */ + break; + + case LEAF_ifLastChange: + value->v.uint32 = + ticks_get_timeval(&ifp->mib.ifmd_data.ifi_lastchange); + break; + + case LEAF_ifInOctets: + value->v.uint32 = ifp->mib.ifmd_data.ifi_ibytes; + break; + + case LEAF_ifInUcastPkts: + value->v.uint32 = ifp->mib.ifmd_data.ifi_ipackets - + ifp->mib.ifmd_data.ifi_imcasts; + break; + + case LEAF_ifInNUcastPkts: + value->v.uint32 = ifp->mib.ifmd_data.ifi_imcasts; + break; + + case LEAF_ifInDiscards: + value->v.uint32 = ifp->mib.ifmd_data.ifi_iqdrops; + break; + + case LEAF_ifInErrors: + value->v.uint32 = ifp->mib.ifmd_data.ifi_ierrors; + break; + + case LEAF_ifInUnknownProtos: + value->v.uint32 = ifp->mib.ifmd_data.ifi_noproto; + break; + + case LEAF_ifOutOctets: + value->v.uint32 = ifp->mib.ifmd_data.ifi_obytes; + break; + + case LEAF_ifOutUcastPkts: + value->v.uint32 = ifp->mib.ifmd_data.ifi_opackets - + ifp->mib.ifmd_data.ifi_omcasts; + break; + + case LEAF_ifOutNUcastPkts: + value->v.uint32 = ifp->mib.ifmd_data.ifi_omcasts; + break; + + case LEAF_ifOutDiscards: + value->v.uint32 = ifp->mib.ifmd_snd_drops; + break; + + case LEAF_ifOutErrors: + value->v.uint32 = ifp->mib.ifmd_data.ifi_oerrors; + break; + + case LEAF_ifOutQLen: + value->v.uint32 = ifp->mib.ifmd_snd_len; + break; + + case LEAF_ifSpecific: + value->v.oid = ifp->spec_oid; + break; + } + return (ret); +} + +/* + * IfXtable entry + */ +int +op_ifxtable(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + struct mibif *ifp = NULL; + int ret; + struct ifchange *ifc; + struct asn_oid idx; + + switch (op) { + + again: + if (op != SNMP_OP_GETNEXT) + return (SNMP_ERR_NOSUCHNAME); + /* FALLTHROUGH */ + + case SNMP_OP_GETNEXT: + if ((ifp = NEXT_OBJECT_INT(&mibif_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + value->var.len = sub + 1; + value->var.subs[sub] = ifp->index; + break; + + case SNMP_OP_GET: + if (value->var.len - sub != 1) + return (SNMP_ERR_NOSUCHNAME); + if ((ifp = mib_find_if(value->var.subs[sub])) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if (value->var.len - sub != 1) + return (SNMP_ERR_NO_CREATION); + if ((ifp = mib_find_if(value->var.subs[sub])) == NULL) + return (SNMP_ERR_NO_CREATION); + + idx.len = 1; + idx.subs[0] = ifp->index; + + if ((ifc = (struct ifchange *)snmp_dep_lookup(ctx, + &oid_ifTable, &idx, sizeof(*ifc), ifchange_func)) == NULL) + return (SNMP_ERR_RES_UNAVAIL); + ifc->ifindex = ifp->index; + + switch (value->var.subs[sub - 1]) { + + case LEAF_ifLinkUpDownTrapEnable: + if (value->v.integer != 1 && value->v.integer != 2) + return (SNMP_ERR_WRONG_VALUE); + if (ifc->set & IFC_TRAPS) + return (SNMP_ERR_INCONS_VALUE); + ifc->set |= IFC_TRAPS; + ifc->traps = (value->v.integer == 1) ? 1 : 0; + return (SNMP_ERR_NOERROR); + + case LEAF_ifPromiscuousMode: + if (value->v.integer != 1 && value->v.integer != 2) + return (SNMP_ERR_WRONG_VALUE); + if (ifc->set & IFC_PROMISC) + return (SNMP_ERR_INCONS_VALUE); + ifc->set |= IFC_PROMISC; + ifc->promisc = (value->v.integer == 1) ? 1 : 0; + return (SNMP_ERR_NOERROR); + } + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + } + + if (ifp->mibtick < this_tick) + (void)mib_fetch_ifmib(ifp); + + ret = SNMP_ERR_NOERROR; + switch (value->var.subs[sub - 1]) { + + case LEAF_ifName: + ret = string_get(value, ifp->name, -1); + break; + + case LEAF_ifInMulticastPkts: + value->v.uint32 = ifp->mib.ifmd_data.ifi_imcasts; + break; + + case LEAF_ifInBroadcastPkts: + value->v.uint32 = 0; + break; + + case LEAF_ifOutMulticastPkts: + value->v.uint32 = ifp->mib.ifmd_data.ifi_omcasts; + break; + + case LEAF_ifOutBroadcastPkts: + value->v.uint32 = 0; + break; + + case LEAF_ifHCInOctets: + if (!(ifp->flags & MIBIF_HIGHSPEED)) + goto again; + value->v.counter64 = MIBIF_PRIV(ifp)->hc_inoctets; + break; + + case LEAF_ifHCInUcastPkts: + if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED))) + goto again; + value->v.counter64 = MIBIF_PRIV(ifp)->hc_ipackets - + MIBIF_PRIV(ifp)->hc_imcasts; + break; + + case LEAF_ifHCInMulticastPkts: + if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED))) + goto again; + value->v.counter64 = MIBIF_PRIV(ifp)->hc_imcasts; + break; + + case LEAF_ifHCInBroadcastPkts: + if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED))) + goto again; + value->v.counter64 = 0; + break; + + case LEAF_ifHCOutOctets: + if (!(ifp->flags & MIBIF_HIGHSPEED)) + goto again; + value->v.counter64 = MIBIF_PRIV(ifp)->hc_outoctets; + break; + + case LEAF_ifHCOutUcastPkts: + if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED))) + goto again; + value->v.counter64 = MIBIF_PRIV(ifp)->hc_opackets - + MIBIF_PRIV(ifp)->hc_omcasts; + break; + + case LEAF_ifHCOutMulticastPkts: + if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED))) + goto again; + value->v.counter64 = MIBIF_PRIV(ifp)->hc_omcasts; + break; + + case LEAF_ifHCOutBroadcastPkts: + if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED))) + goto again; + value->v.counter64 = 0; + break; + + case LEAF_ifLinkUpDownTrapEnable: + value->v.integer = ifp->trap_enable ? 1 : 2; + break; + + case LEAF_ifHighSpeed: + value->v.integer = + (ifp->mib.ifmd_data.ifi_baudrate + 499999) / 1000000; + break; + + case LEAF_ifPromiscuousMode: + value->v.integer = + (ifp->mib.ifmd_flags & IFF_PROMISC) ? 1 : 2; + break; + + case LEAF_ifConnectorPresent: + value->v.integer = ifp->has_connector ? 1 : 2; + break; + + case LEAF_ifAlias: + ret = string_get(value, MIBIF_PRIV(ifp)->alias, -1); + break; + + case LEAF_ifCounterDiscontinuityTime: + if (ifp->counter_disc > start_tick) + value->v.uint32 = ifp->counter_disc - start_tick; + else + value->v.uint32 = 0; + break; + } + return (ret); +} Property changes on: vendor/bsnmp/1.13/snmp_mibII/mibII_interfaces.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/mibII_ip.c =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/mibII_ip.c (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/mibII_ip.c (revision 336778) @@ -0,0 +1,493 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmp_mibII/mibII_ip.c,v 1.11 2005/05/23 09:03:40 brandt_h Exp $ + * + * ip group scalars. + */ +#include "mibII.h" +#include "mibII_oid.h" +#include +#include +#include +#include +#include + +static struct ipstat ipstat; +static u_int ip_idrop; +static struct icmpstat icmpstat; + +static int ip_forwarding; +static int ip_defttl; +static uint64_t ip_tick; + +static uint64_t ipstat_tick; + +static int +fetch_ipstat(void) +{ + size_t len; + + len = sizeof(ipstat); + if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, NULL, 0) == -1) { + syslog(LOG_ERR, "net.inet.ip.stats: %m"); + return (-1); + } + if (len != sizeof(ipstat)) { + syslog(LOG_ERR, "net.inet.ip.stats: wrong size"); + return (-1); + } + len = sizeof(ip_idrop); + if (sysctlbyname("net.inet.ip.intr_queue_drops", &ip_idrop, &len, NULL, 0) == -1) + syslog(LOG_WARNING, "net.inet.ip.intr_queue_drops: %m"); + if (len != sizeof(ip_idrop)) { + syslog(LOG_WARNING, "net.inet.ip.intr_queue_drops: wrong size"); + ip_idrop = 0; + } + len = sizeof(icmpstat); + if (sysctlbyname("net.inet.icmp.stats", &icmpstat, &len, NULL, 0) == -1) { + syslog(LOG_ERR, "net.inet.icmp.stats: %m"); + return (-1); + } + if (len != sizeof(icmpstat)) { + syslog(LOG_ERR, "net.inet.icmp.stats: wrong size"); + return (-1); + } + + ipstat_tick = get_ticks(); + return (0); +} + +static int +fetch_ip(void) +{ + size_t len; + + len = sizeof(ip_forwarding); + if (sysctlbyname("net.inet.ip.forwarding", &ip_forwarding, &len, + NULL, 0) == -1) { + syslog(LOG_ERR, "net.inet.ip.forwarding: %m"); + return (-1); + } + if (len != sizeof(ip_forwarding)) { + syslog(LOG_ERR, "net.inet.ip.forwarding: wrong size"); + return (-1); + } + + len = sizeof(ip_defttl); + if (sysctlbyname("net.inet.ip.ttl", &ip_defttl, &len, + NULL, 0) == -1) { + syslog(LOG_ERR, "net.inet.ip.ttl: %m"); + return (-1); + } + if (len != sizeof(ip_defttl)) { + syslog(LOG_ERR, "net.inet.ip.ttl: wrong size"); + return (-1); + } + + ip_tick = get_ticks(); + return (0); +} + +static int +ip_forward(int forw, int *old) +{ + size_t olen; + + olen = sizeof(*old); + if (sysctlbyname("net.inet.ip.forwarding", old, old ? &olen : NULL, + &forw, sizeof(forw)) == -1) { + syslog(LOG_ERR, "set net.inet.ip.forwarding: %m"); + return (-1); + } + ip_forwarding = forw; + return (0); +} + +static int +ip_setttl(int ttl, int *old) +{ + size_t olen; + + olen = sizeof(*old); + if (sysctlbyname("net.inet.ip.ttl", old, old ? &olen : NULL, + &ttl, sizeof(ttl)) == -1) { + syslog(LOG_ERR, "set net.inet.ip.ttl: %m"); + return (-1); + } + ip_defttl = ttl; + return (0); +} + +/* + * READ/WRITE ip group. + */ +int +op_ip(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int idx __unused, enum snmp_op op) +{ + int old = 0; + + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + break; + + case SNMP_OP_SET: + if (ip_tick < this_tick) + if (fetch_ip() == -1) + return (SNMP_ERR_GENERR); + + switch (value->var.subs[sub - 1]) { + + case LEAF_ipForwarding: + ctx->scratch->int1 = ip_forwarding ? 1 : 2; + ctx->scratch->int2 = value->v.integer; + if (value->v.integer == 1) { + if (!ip_forwarding && ip_forward(1, &old)) + return (SNMP_ERR_GENERR); + ctx->scratch->int1 = old ? 1 : 2; + } else if (value->v.integer == 2) { + if (ip_forwarding && ip_forward(0, &old)) + return (SNMP_ERR_GENERR); + ctx->scratch->int1 = old; + } else + return (SNMP_ERR_WRONG_VALUE); + break; + + case LEAF_ipDefaultTTL: + ctx->scratch->int1 = ip_defttl; + ctx->scratch->int2 = value->v.integer; + if (value->v.integer < 1 || value->v.integer > 255) + return (SNMP_ERR_WRONG_VALUE); + if (ip_defttl != value->v.integer && + ip_setttl(value->v.integer, &old)) + return (SNMP_ERR_GENERR); + ctx->scratch->int1 = old; + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + switch (value->var.subs[sub - 1]) { + + case LEAF_ipForwarding: + if (ctx->scratch->int1 == 1) { + if (ctx->scratch->int2 == 2) + (void)ip_forward(1, NULL); + } else { + if (ctx->scratch->int2 == 1) + (void)ip_forward(0, NULL); + } + break; + + case LEAF_ipDefaultTTL: + if (ctx->scratch->int1 != ctx->scratch->int2) + (void)ip_setttl(ctx->scratch->int1, NULL); + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + } + + if (ip_tick < this_tick) + if (fetch_ip() == -1) + return (SNMP_ERR_GENERR); + + switch (value->var.subs[sub - 1]) { + + case LEAF_ipForwarding: + value->v.integer = ip_forwarding ? 1 : 2; + break; + + case LEAF_ipDefaultTTL: + value->v.integer = ip_defttl; + break; + } + return (SNMP_ERR_NOERROR); +} + +/* + * READ-ONLY statistics ip group. + */ +int +op_ipstat(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int idx __unused, enum snmp_op op) +{ + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + break; + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + abort(); + } + + if (ipstat_tick < this_tick) + fetch_ipstat(); + + switch (value->var.subs[sub - 1]) { + + case LEAF_ipInReceives: + value->v.uint32 = ipstat.ips_total; + break; + + case LEAF_ipInHdrErrors: + value->v.uint32 = ipstat.ips_badsum + ipstat.ips_tooshort + + ipstat.ips_toosmall + ipstat.ips_badhlen + + ipstat.ips_badlen + ipstat.ips_badvers + + + ipstat.ips_toolong; + break; + + case LEAF_ipInAddrErrors: + value->v.uint32 = ipstat.ips_cantforward; + break; + + case LEAF_ipForwDatagrams: + value->v.uint32 = ipstat.ips_forward; + break; + + case LEAF_ipInUnknownProtos: + value->v.uint32 = ipstat.ips_noproto; + break; + + case LEAF_ipInDiscards: + value->v.uint32 = ip_idrop; + break; + + case LEAF_ipInDelivers: + value->v.uint32 = ipstat.ips_delivered; + break; + + case LEAF_ipOutRequests: + value->v.uint32 = ipstat.ips_localout; + break; + + case LEAF_ipOutDiscards: + value->v.uint32 = ipstat.ips_odropped; + break; + + case LEAF_ipOutNoRoutes: + value->v.uint32 = ipstat.ips_noroute; + break; + + case LEAF_ipReasmTimeout: + value->v.integer = IPFRAGTTL; + break; + + case LEAF_ipReasmReqds: + value->v.uint32 = ipstat.ips_fragments; + break; + + case LEAF_ipReasmOKs: + value->v.uint32 = ipstat.ips_reassembled; + break; + + case LEAF_ipReasmFails: + value->v.uint32 = ipstat.ips_fragdropped + + ipstat.ips_fragtimeout; + break; + + case LEAF_ipFragOKs: + value->v.uint32 = ipstat.ips_fragmented; + break; + + case LEAF_ipFragFails: + value->v.uint32 = ipstat.ips_cantfrag; + break; + + case LEAF_ipFragCreates: + value->v.uint32 = ipstat.ips_ofragments; + break; + } + return (SNMP_ERR_NOERROR); +} + +/* + * READ-ONLY statistics icmp group. + */ +int +op_icmpstat(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int idx __unused, enum snmp_op op) +{ + u_int i; + + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + break; + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + abort(); + } + + if (ipstat_tick < this_tick) + fetch_ipstat(); + + switch (value->var.subs[sub - 1]) { + + case LEAF_icmpInMsgs: + value->v.integer = 0; + for (i = 0; i <= ICMP_MAXTYPE; i++) + value->v.integer += icmpstat.icps_inhist[i]; + value->v.integer += icmpstat.icps_tooshort + + icmpstat.icps_checksum; + /* missing: bad type and packets on faith */ + break; + + case LEAF_icmpInErrors: + value->v.integer = icmpstat.icps_tooshort + + icmpstat.icps_checksum + + icmpstat.icps_badlen + + icmpstat.icps_badcode + + icmpstat.icps_bmcastecho + + icmpstat.icps_bmcasttstamp; + break; + + case LEAF_icmpInDestUnreachs: + value->v.integer = icmpstat.icps_inhist[ICMP_UNREACH]; + break; + + case LEAF_icmpInTimeExcds: + value->v.integer = icmpstat.icps_inhist[ICMP_TIMXCEED]; + break; + + case LEAF_icmpInParmProbs: + value->v.integer = icmpstat.icps_inhist[ICMP_PARAMPROB]; + break; + + case LEAF_icmpInSrcQuenchs: + value->v.integer = icmpstat.icps_inhist[ICMP_SOURCEQUENCH]; + break; + + case LEAF_icmpInRedirects: + value->v.integer = icmpstat.icps_inhist[ICMP_REDIRECT]; + break; + + case LEAF_icmpInEchos: + value->v.integer = icmpstat.icps_inhist[ICMP_ECHO]; + break; + + case LEAF_icmpInEchoReps: + value->v.integer = icmpstat.icps_inhist[ICMP_ECHOREPLY]; + break; + + case LEAF_icmpInTimestamps: + value->v.integer = icmpstat.icps_inhist[ICMP_TSTAMP]; + break; + + case LEAF_icmpInTimestampReps: + value->v.integer = icmpstat.icps_inhist[ICMP_TSTAMPREPLY]; + break; + + case LEAF_icmpInAddrMasks: + value->v.integer = icmpstat.icps_inhist[ICMP_MASKREQ]; + break; + + case LEAF_icmpInAddrMaskReps: + value->v.integer = icmpstat.icps_inhist[ICMP_MASKREPLY]; + break; + + case LEAF_icmpOutMsgs: + value->v.integer = 0; + for (i = 0; i <= ICMP_MAXTYPE; i++) + value->v.integer += icmpstat.icps_outhist[i]; + value->v.integer += icmpstat.icps_badaddr + + icmpstat.icps_noroute; + break; + + case LEAF_icmpOutErrors: + value->v.integer = icmpstat.icps_badaddr + + icmpstat.icps_noroute; + break; + + case LEAF_icmpOutDestUnreachs: + value->v.integer = icmpstat.icps_outhist[ICMP_UNREACH]; + break; + + case LEAF_icmpOutTimeExcds: + value->v.integer = icmpstat.icps_outhist[ICMP_TIMXCEED]; + break; + + case LEAF_icmpOutParmProbs: + value->v.integer = icmpstat.icps_outhist[ICMP_PARAMPROB]; + break; + + case LEAF_icmpOutSrcQuenchs: + value->v.integer = icmpstat.icps_outhist[ICMP_SOURCEQUENCH]; + break; + + case LEAF_icmpOutRedirects: + value->v.integer = icmpstat.icps_outhist[ICMP_REDIRECT]; + break; + + case LEAF_icmpOutEchos: + value->v.integer = icmpstat.icps_outhist[ICMP_ECHO]; + break; + + case LEAF_icmpOutEchoReps: + value->v.integer = icmpstat.icps_outhist[ICMP_ECHOREPLY]; + break; + + case LEAF_icmpOutTimestamps: + value->v.integer = icmpstat.icps_outhist[ICMP_TSTAMP]; + break; + + case LEAF_icmpOutTimestampReps: + value->v.integer = icmpstat.icps_outhist[ICMP_TSTAMPREPLY]; + break; + + case LEAF_icmpOutAddrMasks: + value->v.integer = icmpstat.icps_outhist[ICMP_MASKREQ]; + break; + + case LEAF_icmpOutAddrMaskReps: + value->v.integer = icmpstat.icps_outhist[ICMP_MASKREPLY]; + break; + } + return (SNMP_ERR_NOERROR); +} Property changes on: vendor/bsnmp/1.13/snmp_mibII/mibII_ip.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/mibII_ipaddr.c =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/mibII_ipaddr.c (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/mibII_ipaddr.c (revision 336778) @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2001-2002 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmp_mibII/mibII_ipaddr.c,v 1.10 2005/10/04 11:21:35 brandt_h Exp $ + * + * IP address table. This table is writeable! + * + * Writing to this table will add a new IP address to the interface. + * An address can be deleted with writing the interface index 0. + */ +#include "mibII.h" +#include "mibII_oid.h" + +static const struct asn_oid + oid_ipAddrTable = OIDX_ipAddrTable; + +/* + * Be careful not to hold any pointers during the SET processing - the + * interface and address lists can be relocated at any time. + */ +struct update { + struct snmp_dependency dep; + + uint32_t set; + struct in_addr addr; + struct in_addr mask; + int bcast; + u_int ifindex; + + uint32_t rb; + struct in_addr rb_mask; + struct in_addr rb_bcast; +}; +#define UPD_IFINDEX 0x0001 +#define UPD_MASK 0x0002 +#define UPD_BCAST 0x0004 +#define RB_CREATE 0x0001 +#define RB_DESTROY 0x0002 +#define RB_MODIFY 0x0004 + +/* + * Create a new interface address + */ +static int +create(struct update *upd) +{ + struct in_addr bcast; + struct mibifa *ifa; + + if (!(upd->set & UPD_MASK)) { + if (IN_CLASSA(ntohl(upd->addr.s_addr))) + upd->mask.s_addr = htonl(IN_CLASSA_NET); + else if (IN_CLASSB(ntohl(upd->addr.s_addr))) + upd->mask.s_addr = htonl(IN_CLASSB_NET); + else if (IN_CLASSC(ntohl(upd->addr.s_addr))) + upd->mask.s_addr = htonl(IN_CLASSC_NET); + else + upd->mask.s_addr = 0xffffffff; + } + + bcast.s_addr = upd->addr.s_addr & upd->mask.s_addr; + if (!(upd->set & UPD_BCAST) || upd->bcast) { + uint32_t tmp = ~ntohl(upd->mask.s_addr); + bcast.s_addr |= htonl(0xffffffff & ~tmp); + } + + if ((ifa = mib_create_ifa(upd->ifindex, upd->addr, upd->mask, bcast)) + == NULL) + return (SNMP_ERR_GENERR); + + upd->rb |= RB_CREATE; + return (SNMP_ERR_NOERROR); +} + +/* + * Modify the netmask or broadcast address. The ifindex cannot be + * changed (obviously). + */ +static int +modify(struct update *upd, struct mibifa *ifa) +{ + struct mibif *ifp; + + if ((ifp = mib_find_if(ifa->ifindex)) == NULL) + return (SNMP_ERR_WRONG_VALUE); + if ((upd->set & UPD_IFINDEX) && upd->ifindex != ifa->ifindex) + return (SNMP_ERR_INCONS_VALUE); + + upd->rb_mask = ifa->inmask; + upd->rb_bcast = ifa->inbcast; + if (((upd->set & UPD_MASK) && upd->mask.s_addr != ifa->inmask.s_addr) || + (upd->set & UPD_BCAST)) { + if (upd->set & UPD_MASK) + ifa->inmask = upd->mask; + if (upd->set & UPD_BCAST) { + ifa->inbcast.s_addr = ifa->inaddr.s_addr + & ifa->inmask.s_addr; + if (upd->bcast) + ifa->inbcast.s_addr |= 0xffffffff + & ~ifa->inmask.s_addr; + } + if (mib_modify_ifa(ifa)) { + syslog(LOG_ERR, "set netmask/bcast: %m"); + ifa->inmask = upd->rb_mask; + ifa->inbcast = upd->rb_bcast; + mib_unmodify_ifa(ifa); + return (SNMP_ERR_GENERR); + } + upd->rb |= RB_MODIFY; + } + return (SNMP_ERR_NOERROR); +} + +/* + * Destroy the given row in the table. We remove the address from the + * system, but keep the structure around for the COMMIT. It's deleted + * only in the FINISH operation. + */ +static int +destroy(struct snmp_context *ctx __unused, struct update *upd, + struct mibifa *ifa) +{ + if (mib_destroy_ifa(ifa)) + return (SNMP_ERR_GENERR); + upd->rb |= RB_DESTROY; + return (SNMP_ERR_NOERROR); +} + +/* + * This function is called to commit/rollback a SET on an IpAddrEntry + */ +static int +update_func(struct snmp_context *ctx, struct snmp_dependency *dep, + enum snmp_depop op) +{ + struct update *upd = (struct update *)dep; + struct mibifa *ifa; + + switch (op) { + + case SNMP_DEPOP_COMMIT: + if ((ifa = mib_find_ifa(upd->addr)) == NULL) { + /* non existing entry - must have ifindex */ + if (!(upd->set & UPD_IFINDEX)) + return (SNMP_ERR_INCONS_NAME); + return (create(upd)); + } + /* existing entry */ + if ((upd->set & UPD_IFINDEX) && upd->ifindex == 0) { + /* delete */ + return (destroy(ctx, upd, ifa)); + } + /* modify entry */ + return (modify(upd, ifa)); + + case SNMP_DEPOP_ROLLBACK: + if ((ifa = mib_find_ifa(upd->addr)) == NULL) { + /* ups */ + mib_iflist_bad = 1; + return (SNMP_ERR_NOERROR); + } + if (upd->rb & RB_CREATE) { + mib_uncreate_ifa(ifa); + return (SNMP_ERR_NOERROR); + } + if (upd->rb & RB_DESTROY) { + mib_undestroy_ifa(ifa); + return (SNMP_ERR_NOERROR); + } + if (upd->rb & RB_MODIFY) { + ifa->inmask = upd->rb_mask; + ifa->inbcast = upd->rb_bcast; + mib_unmodify_ifa(ifa); + return (SNMP_ERR_NOERROR); + } + return (SNMP_ERR_NOERROR); + + case SNMP_DEPOP_FINISH: + if ((upd->rb & RB_DESTROY) && + (ifa = mib_find_ifa(upd->addr)) != NULL && + (ifa->flags & MIBIFA_DESTROYED)) { + TAILQ_REMOVE(&mibifa_list, ifa, link); + free(ifa); + } + return (SNMP_ERR_NOERROR); + } + abort(); +} + +/**********************************************************************/ +/* + * ACTION + */ +int +op_ipaddr(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx, enum snmp_op op) +{ + asn_subid_t which; + struct mibifa *ifa; + struct update *upd; + struct asn_oid idx; + u_char ipaddr[4]; + + which = value->var.subs[sub - 1]; + + ifa = NULL; + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((ifa = NEXT_OBJECT_OID(&mibifa_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &ifa->index); + break; + + case SNMP_OP_GET: + if ((ifa = FIND_OBJECT_OID(&mibifa_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if (index_decode(&value->var, sub, iidx, ipaddr)) + return (SNMP_ERR_NO_CREATION); + ifa = FIND_OBJECT_OID(&mibifa_list, &value->var, sub); + idx.len = 4; + idx.subs[0] = ipaddr[0]; + idx.subs[1] = ipaddr[1]; + idx.subs[2] = ipaddr[2]; + idx.subs[3] = ipaddr[3]; + + if ((upd = (struct update *)snmp_dep_lookup(ctx, + &oid_ipAddrTable, &idx, sizeof(*upd), update_func)) == NULL) + return (SNMP_ERR_RES_UNAVAIL); + + upd->addr.s_addr = htonl((ipaddr[0] << 24) | (ipaddr[1] << 16) | + (ipaddr[2] << 8) | (ipaddr[3] << 0)); + + switch (which) { + + case LEAF_ipAdEntIfIndex: + if (upd->set & UPD_IFINDEX) + return (SNMP_ERR_INCONS_VALUE); + if (value->v.integer < 0 || + value->v.integer > 0x07fffffff) + return (SNMP_ERR_WRONG_VALUE); + if (ifa != NULL) { + if (ifa->ifindex != (u_int)value->v.integer && + value->v.integer != 0) + return (SNMP_ERR_INCONS_VALUE); + } + upd->set |= UPD_IFINDEX; + upd->ifindex = (u_int)value->v.integer; + break; + + case LEAF_ipAdEntNetMask: + if (upd->set & UPD_MASK) + return (SNMP_ERR_INCONS_VALUE); + upd->mask.s_addr = htonl((value->v.ipaddress[0] << 24) + | (value->v.ipaddress[1] << 16) + | (value->v.ipaddress[2] << 8) + | (value->v.ipaddress[3] << 0)); + upd->set |= UPD_MASK; + break; + + case LEAF_ipAdEntBcastAddr: + if (upd->set & UPD_BCAST) + return (SNMP_ERR_INCONS_VALUE); + if (value->v.integer != 0 && value->v.integer != 1) + return (SNMP_ERR_WRONG_VALUE); + upd->bcast = value->v.integer; + upd->set |= UPD_BCAST; + break; + + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + } + + switch (which) { + + case LEAF_ipAdEntAddr: + value->v.ipaddress[0] = ifa->index.subs[0]; + value->v.ipaddress[1] = ifa->index.subs[1]; + value->v.ipaddress[2] = ifa->index.subs[2]; + value->v.ipaddress[3] = ifa->index.subs[3]; + break; + + case LEAF_ipAdEntIfIndex: + if (ifa->flags & MIBIFA_DESTROYED) + value->v.integer = 0; + else + value->v.integer = ifa->ifindex; + break; + + case LEAF_ipAdEntNetMask: + value->v.ipaddress[0] = (ntohl(ifa->inmask.s_addr) >> 24) & 0xff; + value->v.ipaddress[1] = (ntohl(ifa->inmask.s_addr) >> 16) & 0xff; + value->v.ipaddress[2] = (ntohl(ifa->inmask.s_addr) >> 8) & 0xff; + value->v.ipaddress[3] = (ntohl(ifa->inmask.s_addr) >> 0) & 0xff; + break; + + case LEAF_ipAdEntBcastAddr: + value->v.integer = ntohl(ifa->inbcast.s_addr) & 1; + break; + + + case LEAF_ipAdEntReasmMaxSize: + value->v.integer = 65535; + break; + } + return (SNMP_ERR_NOERROR); +} Property changes on: vendor/bsnmp/1.13/snmp_mibII/mibII_ipaddr.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/mibII_nettomedia.c =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/mibII_nettomedia.c (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/mibII_nettomedia.c (revision 336778) @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmp_mibII/mibII_nettomedia.c,v 1.8 2004/08/06 08:47:03 brandt Exp $ + * + * Read-only implementation of the Arp table (ipNetToMediaTable) + * + * The problem with the table is, that we don't receive routing message + * when a) an arp table entry is resolved and b) when an arp table entry is + * deleted automatically. Therefor we need to poll the table from time to + * time. + */ +#include "mibII.h" +#include "mibII_oid.h" + +#define ARPREFRESH 30 + +struct mibarp * +mib_find_arp(const struct mibif *ifp, struct in_addr in) +{ + struct mibarp *at; + uint32_t a = ntohl(in.s_addr); + + if (get_ticks() >= mibarpticks + ARPREFRESH) + mib_arp_update(); + + TAILQ_FOREACH(at, &mibarp_list, link) + if (at->index.subs[0] == ifp->index && + (at->index.subs[1] == ((a >> 24) & 0xff)) && + (at->index.subs[2] == ((a >> 16) & 0xff)) && + (at->index.subs[3] == ((a >> 8) & 0xff)) && + (at->index.subs[4] == ((a >> 0) & 0xff))) + return (at); + return (NULL); +} + +struct mibarp * +mib_arp_create(const struct mibif *ifp, struct in_addr in, const u_char *phys, + size_t physlen) +{ + struct mibarp *at; + uint32_t a = ntohl(in.s_addr); + + if ((at = malloc(sizeof(*at))) == NULL) + return (NULL); + at->flags = 0; + + at->index.len = 5; + at->index.subs[0] = ifp->index; + at->index.subs[1] = (a >> 24) & 0xff; + at->index.subs[2] = (a >> 16) & 0xff; + at->index.subs[3] = (a >> 8) & 0xff; + at->index.subs[4] = (a >> 0) & 0xff; + if ((at->physlen = physlen) > sizeof(at->phys)) + at->physlen = sizeof(at->phys); + memcpy(at->phys, phys, at->physlen); + + INSERT_OBJECT_OID(at, &mibarp_list); + + return (at); +} + +void +mib_arp_delete(struct mibarp *at) +{ + TAILQ_REMOVE(&mibarp_list, at, link); + free(at); +} + +int +op_nettomedia(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + struct mibarp *at; + + at = NULL; /* gcc */ + + if (get_ticks() >= mibarpticks + ARPREFRESH) + mib_arp_update(); + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((at = NEXT_OBJECT_OID(&mibarp_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &at->index); + break; + + case SNMP_OP_GET: + if ((at = FIND_OBJECT_OID(&mibarp_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if ((at = FIND_OBJECT_OID(&mibarp_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NO_CREATION); + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + abort(); + } + + switch (value->var.subs[sub - 1]) { + + case LEAF_ipNetToMediaIfIndex: + value->v.integer = at->index.subs[0]; + break; + + case LEAF_ipNetToMediaPhysAddress: + return (string_get(value, at->phys, at->physlen)); + + case LEAF_ipNetToMediaNetAddress: + value->v.ipaddress[0] = at->index.subs[1]; + value->v.ipaddress[1] = at->index.subs[2]; + value->v.ipaddress[2] = at->index.subs[3]; + value->v.ipaddress[3] = at->index.subs[4]; + break; + + case LEAF_ipNetToMediaType: + value->v.integer = (at->flags & MIBARP_PERM) ? 4 : 3; + break; + } + return (SNMP_ERR_NOERROR); +} Property changes on: vendor/bsnmp/1.13/snmp_mibII/mibII_nettomedia.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/mibII_rcvaddr.c =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/mibII_rcvaddr.c (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/mibII_rcvaddr.c (revision 336778) @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmp_mibII/mibII_rcvaddr.c,v 1.9 2004/08/06 08:47:03 brandt Exp $ + * + * Interface receive address table. + */ +#include "mibII.h" +#include "mibII_oid.h" + +/* + * find receive address + */ +struct mibrcvaddr * +mib_find_rcvaddr(u_int ifindex, const u_char *addr, size_t addrlen) +{ + struct mibrcvaddr *rcv; + + TAILQ_FOREACH(rcv, &mibrcvaddr_list, link) + if (rcv->ifindex == ifindex && + rcv->addrlen == addrlen && + memcmp(rcv->addr, addr, addrlen) == 0) + return (rcv); + return (NULL); +} + +/* + * Create receive address + */ +struct mibrcvaddr * +mib_rcvaddr_create(struct mibif *ifp, const u_char *addr, size_t addrlen) +{ + struct mibrcvaddr *rcv; + u_int i; + + if (addrlen + OIDLEN_ifRcvAddressEntry + 1 > ASN_MAXOIDLEN) + return (NULL); + + if ((rcv = malloc(sizeof(*rcv))) == NULL) + return (NULL); + rcv->ifindex = ifp->index; + rcv->addrlen = addrlen; + memcpy(rcv->addr, addr, addrlen); + rcv->flags = 0; + + rcv->index.len = addrlen + 2; + rcv->index.subs[0] = ifp->index; + rcv->index.subs[1] = addrlen; + for (i = 0; i < addrlen; i++) + rcv->index.subs[i + 2] = addr[i]; + + INSERT_OBJECT_OID(rcv, &mibrcvaddr_list); + + return (rcv); +} + +/* + * Delete a receive address + */ +void +mib_rcvaddr_delete(struct mibrcvaddr *rcv) +{ + TAILQ_REMOVE(&mibrcvaddr_list, rcv, link); + free(rcv); +} + +int +op_rcvaddr(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + struct mibrcvaddr *rcv; + + rcv = NULL; /* make compiler happy */ + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((rcv = NEXT_OBJECT_OID(&mibrcvaddr_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &rcv->index); + break; + + case SNMP_OP_GET: + if ((rcv = FIND_OBJECT_OID(&mibrcvaddr_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if ((rcv = FIND_OBJECT_OID(&mibrcvaddr_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NO_CREATION); + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + abort(); + } + + switch (value->var.subs[sub - 1]) { + + case LEAF_ifRcvAddressStatus: + value->v.integer = 1; + break; + + case LEAF_ifRcvAddressType: + value->v.integer = (rcv->flags & MIBRCVADDR_VOLATILE) ? 2 : 3; + break; + } + return (SNMP_ERR_NOERROR); +} Property changes on: vendor/bsnmp/1.13/snmp_mibII/mibII_rcvaddr.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/mibII_route.c =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/mibII_route.c (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/mibII_route.c (revision 336778) @@ -0,0 +1,514 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmp_mibII/mibII_route.c,v 1.9 2005/10/06 07:15:00 brandt_h Exp $ + * + * Routing table + */ + +#ifdef HAVE_SYS_TREE_H +#include +#else +#include "tree.h" +#endif + +#include "mibII.h" +#include "mibII_oid.h" + +struct sroute { + RB_ENTRY(sroute) link; + uint32_t ifindex; + uint8_t index[13]; + uint8_t type; + uint8_t proto; +}; +static RB_HEAD(sroutes, sroute) sroutes = RB_INITIALIZER(&sroutes); + +RB_PROTOTYPE(sroutes, sroute, link, sroute_compare); + +#define ROUTE_UPDATE_INTERVAL (100 * 60 * 10) /* 10 min */ +static uint64_t route_tick; +static u_int route_total; + +/* + * Compare two routes + */ +static int +sroute_compare(struct sroute *s1, struct sroute *s2) +{ + + return (memcmp(s1->index, s2->index, 13)); +} + +static void +sroute_index_append(struct asn_oid *oid, u_int sub, const struct sroute *s) +{ + int i; + + oid->len = sub + 13; + for (i = 0; i < 13; i++) + oid->subs[sub + i] = s->index[i]; +} + +#if 0 +static void +sroute_print(const struct sroute *r) +{ + u_int i; + + for (i = 0; i < 13 - 1; i++) + printf("%u.", r->index[i]); + printf("%u proto=%u type=%u", r->index[i], r->proto, r->type); +} +#endif + +/* + * process routing message + */ +void +mib_sroute_process(struct rt_msghdr *rtm, struct sockaddr *gw, + struct sockaddr *dst, struct sockaddr *mask) +{ + struct sockaddr_in *in_dst, *in_gw; + struct in_addr in_mask; + struct mibif *ifp; + struct sroute key; + struct sroute *r, *r1; + in_addr_t ha; + + if (dst == NULL || gw == NULL || dst->sa_family != AF_INET || + gw->sa_family != AF_INET) + return; + + in_dst = (struct sockaddr_in *)(void *)dst; + in_gw = (struct sockaddr_in *)(void *)gw; + + if (rtm->rtm_flags & RTF_HOST) + in_mask.s_addr = 0xffffffff; + else if (mask == NULL || mask->sa_len == 0) + in_mask.s_addr = 0; + else + in_mask = ((struct sockaddr_in *)(void *)mask)->sin_addr; + + /* build the index */ + ha = ntohl(in_dst->sin_addr.s_addr); + key.index[0] = (ha >> 24) & 0xff; + key.index[1] = (ha >> 16) & 0xff; + key.index[2] = (ha >> 8) & 0xff; + key.index[3] = (ha >> 0) & 0xff; + + ha = ntohl(in_mask.s_addr); + key.index[4] = (ha >> 24) & 0xff; + key.index[5] = (ha >> 16) & 0xff; + key.index[6] = (ha >> 8) & 0xff; + key.index[7] = (ha >> 0) & 0xff; + + /* ToS */ + key.index[8] = 0; + + ha = ntohl(in_gw->sin_addr.s_addr); + key.index[9] = (ha >> 24) & 0xff; + key.index[10] = (ha >> 16) & 0xff; + key.index[11] = (ha >> 8) & 0xff; + key.index[12] = (ha >> 0) & 0xff; + + if (rtm->rtm_type == RTM_DELETE) { + r = RB_FIND(sroutes, &sroutes, &key); + if (r == 0) { +#ifdef DEBUG_ROUTE + syslog(LOG_WARNING, "%s: DELETE: %u.%u.%u.%u " + "%u.%u.%u.%u %u %u.%u.%u.%u not found", __func__, + key.index[0], key.index[1], key.index[2], + key.index[3], key.index[4], key.index[5], + key.index[6], key.index[7], key.index[8], + key.index[9], key.index[10], key.index[11], + key.index[12]); +#endif + return; + } + RB_REMOVE(sroutes, &sroutes, r); + free(r); + route_total--; +#ifdef DEBUG_ROUTE + printf("%s: DELETE: %u.%u.%u.%u " + "%u.%u.%u.%u %u %u.%u.%u.%u\n", __func__, + key.index[0], key.index[1], key.index[2], + key.index[3], key.index[4], key.index[5], + key.index[6], key.index[7], key.index[8], + key.index[9], key.index[10], key.index[11], + key.index[12]); +#endif + return; + } + + /* GET or ADD */ + ifp = NULL; + if ((ifp = mib_find_if_sys(rtm->rtm_index)) == NULL) { + if (rtm->rtm_type == RTM_ADD) { + /* make it a get so the kernel fills the index */ + mib_send_rtmsg(rtm, gw, dst, mask); + return; + } + mib_iflist_bad = 1; + } + + if ((r = malloc(sizeof(*r))) == NULL) { + syslog(LOG_ERR, "%m"); + return; + } + + memcpy(r->index, key.index, sizeof(r->index)); + r->ifindex = (ifp == NULL) ? 0 : ifp->index; + + r->type = (rtm->rtm_flags & RTF_REJECT) ? 2 : 4; + + /* cannot really know, what protocol it runs */ + r->proto = (rtm->rtm_flags & RTF_LOCAL) ? 2 : + (rtm->rtm_flags & RTF_STATIC) ? 3 : + (rtm->rtm_flags & RTF_DYNAMIC) ? 4 : 10; + + r1 = RB_INSERT(sroutes, &sroutes, r); + if (r1 != NULL) { +#ifdef DEBUG_ROUTE + syslog(LOG_WARNING, "%s: %u.%u.%u.%u " + "%u.%u.%u.%u %u %u.%u.%u.%u duplicate route", __func__, + key.index[0], key.index[1], key.index[2], + key.index[3], key.index[4], key.index[5], + key.index[6], key.index[7], key.index[8], + key.index[9], key.index[10], key.index[11], + key.index[12]); +#endif + r1->ifindex = r->ifindex; + r1->type = r->type; + r1->proto = r->proto; + free(r); + return; + } + + route_total++; +#ifdef DEBUG_ROUTE + printf("%s: ADD/GET: %u.%u.%u.%u " + "%u.%u.%u.%u %u %u.%u.%u.%u\n", __func__, + key.index[0], key.index[1], key.index[2], + key.index[3], key.index[4], key.index[5], + key.index[6], key.index[7], key.index[8], + key.index[9], key.index[10], key.index[11], + key.index[12]); +#endif +} + +int +mib_fetch_route(void) +{ + u_char *rtab, *next; + size_t len; + struct sroute *r, *r1; + struct rt_msghdr *rtm; + struct sockaddr *addrs[RTAX_MAX]; + + if (route_tick != 0 && route_tick + ROUTE_UPDATE_INTERVAL > this_tick) + return (0); + + /* + * Remove all routes + */ + r = RB_MIN(sroutes, &sroutes); + while (r != NULL) { + r1 = RB_NEXT(sroutes, &sroutes, r); + RB_REMOVE(sroutes, &sroutes, r); + free(r); + r = r1; + } + route_total = 0; + + if ((rtab = mib_fetch_rtab(AF_INET, NET_RT_DUMP, 0, &len)) == NULL) + return (-1); + + next = rtab; + for (next = rtab; next < rtab + len; next += rtm->rtm_msglen) { + rtm = (struct rt_msghdr *)(void *)next; + if (rtm->rtm_type != RTM_GET || + !(rtm->rtm_flags & RTF_UP)) + continue; + mib_extract_addrs(rtm->rtm_addrs, (u_char *)(rtm + 1), addrs); + + + mib_sroute_process(rtm, addrs[RTAX_GATEWAY], addrs[RTAX_DST], + addrs[RTAX_NETMASK]); + } + +#if 0 + u_int n = 0; + r = RB_MIN(sroutes, &sroutes); + while (r != NULL) { + printf("%u: ", n++); + sroute_print(r); + printf("\n"); + r = RB_NEXT(sroutes, &sroutes, r); + } +#endif + free(rtab); + route_tick = get_ticks(); + + return (0); +} + +/** + * Find a route in the table. + */ +static struct sroute * +sroute_get(const struct asn_oid *oid, u_int sub) +{ + struct sroute key; + int i; + + if (oid->len - sub != 13) + return (NULL); + for (i = 0; i < 13; i++) + key.index[i] = oid->subs[sub + i]; + return (RB_FIND(sroutes, &sroutes, &key)); +} + +/** + * Find next route in the table. There is no such RB_ macro, so must + * dig into the innards of the RB stuff. + */ +static struct sroute * +sroute_getnext(struct asn_oid *oid, u_int sub) +{ + u_int i; + int comp; + struct sroute key; + struct sroute *best; + struct sroute *s; + + /* + * We now, that the OID is at least the tableEntry OID. If it is, + * the user wants the first route. + */ + if (oid->len == sub) + return (RB_MIN(sroutes, &sroutes)); + + /* + * This is also true for any index that consists of zeros and is + * shorter than the full index. + */ + if (oid->len < sub + 13) { + for (i = sub; i < oid->len; i++) + if (oid->subs[i] != 0) + break; + if (i == oid->len) + return (RB_MIN(sroutes, &sroutes)); + + /* + * Now if the index is too short, we fill it with zeros and then + * subtract one from the index. We can do this, because we now, + * that there is at least one index element that is not zero. + */ + for (i = oid->len; i < sub + 13; i++) + oid->subs[i] = 0; + + for (i = sub + 13 - 1; i >= sub; i--) { + if (oid->subs[i] != 0) { + oid->subs[i]--; + break; + } + oid->subs[i] = ASN_MAXID; + } + oid->len = sub + 13; + } + + /* build the index */ + for (i = sub; i < sub + 13; i++) + key.index[i - sub] = oid->subs[i]; + + /* now find the element */ + best = NULL; + s = RB_ROOT(&sroutes); + + while (s != NULL) { + comp = sroute_compare(&key, s); + if (comp >= 0) { + /* The current element is smaller than what we search. + * Forget about it and move to the right subtree. */ + s = RB_RIGHT(s, link); + continue; + } + /* the current element is larger than what we search. + * forget about the right subtree (its even larger), but + * the current element may be what we need. */ + if (best == NULL || sroute_compare(s, best) < 0) + /* this one's better */ + best = s; + + s = RB_LEFT(s, link); + } + return (best); +} + +/* + * Table + */ +int +op_route_table(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + struct sroute *r; + + if (mib_fetch_route() == -1) + return (SNMP_ERR_GENERR); + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((r = sroute_getnext(&value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + sroute_index_append(&value->var, sub, r); + break; + + case SNMP_OP_GET: + if ((r = sroute_get(&value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if ((r = sroute_get(&value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + abort(); + + default: + abort(); + } + + switch (value->var.subs[sub - 1]) { + + case LEAF_ipCidrRouteDest: + value->v.ipaddress[0] = r->index[0]; + value->v.ipaddress[1] = r->index[1]; + value->v.ipaddress[2] = r->index[2]; + value->v.ipaddress[3] = r->index[3]; + break; + + case LEAF_ipCidrRouteMask: + value->v.ipaddress[0] = r->index[4]; + value->v.ipaddress[1] = r->index[5]; + value->v.ipaddress[2] = r->index[6]; + value->v.ipaddress[3] = r->index[7]; + break; + + case LEAF_ipCidrRouteTos: + value->v.integer = r->index[8]; + break; + + case LEAF_ipCidrRouteNextHop: + value->v.ipaddress[0] = r->index[9]; + value->v.ipaddress[1] = r->index[10]; + value->v.ipaddress[2] = r->index[11]; + value->v.ipaddress[3] = r->index[12]; + break; + + case LEAF_ipCidrRouteIfIndex: + value->v.integer = r->ifindex; + break; + + case LEAF_ipCidrRouteType: + value->v.integer = r->type; + break; + + case LEAF_ipCidrRouteProto: + value->v.integer = r->proto; + break; + + case LEAF_ipCidrRouteAge: + value->v.integer = 0; + break; + + case LEAF_ipCidrRouteInfo: + value->v.oid = oid_zeroDotZero; + break; + + case LEAF_ipCidrRouteNextHopAS: + value->v.integer = 0; + break; + + case LEAF_ipCidrRouteMetric1: + case LEAF_ipCidrRouteMetric2: + case LEAF_ipCidrRouteMetric3: + case LEAF_ipCidrRouteMetric4: + case LEAF_ipCidrRouteMetric5: + value->v.integer = -1; + break; + + case LEAF_ipCidrRouteStatus: + value->v.integer = 1; + break; + } + return (SNMP_ERR_NOERROR); +} + +/* + * scalars + */ +int +op_route(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + break; + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + abort(); + } + + if (mib_fetch_route() == -1) + return (SNMP_ERR_GENERR); + + switch (value->var.subs[sub - 1]) { + + case LEAF_ipCidrRouteNumber: + value->v.uint32 = route_total; + break; + + } + return (SNMP_ERR_NOERROR); +} + +RB_GENERATE(sroutes, sroute, link, sroute_compare); Property changes on: vendor/bsnmp/1.13/snmp_mibII/mibII_route.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/mibII_tcp.c =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/mibII_tcp.c (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/mibII_tcp.c (revision 336778) @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmp_mibII/mibII_tcp.c,v 1.7 2005/05/23 09:03:42 brandt_h Exp $ + * + * tcp + */ +#include "mibII.h" +#include "mibII_oid.h" +#include +#include +#include +#include +#include +#include + +struct tcp_index { + struct asn_oid index; + struct xtcpcb *tp; +}; + +static uint64_t tcp_tick; +static uint64_t tcp_stats_tick; +static struct tcpstat tcpstat; +static uint64_t tcps_states[TCP_NSTATES]; +static struct xinpgen *xinpgen; +static size_t xinpgen_len; +static u_int tcp_total; + +static u_int oidnum; +static struct tcp_index *tcpoids; + +static int +tcp_compare(const void *p1, const void *p2) +{ + const struct tcp_index *t1 = p1; + const struct tcp_index *t2 = p2; + + return (asn_compare_oid(&t1->index, &t2->index)); +} + +static int +fetch_tcp_stats(void) +{ + size_t len; + + len = sizeof(tcpstat); + if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, NULL, 0) == -1) { + syslog(LOG_ERR, "net.inet.tcp.stats: %m"); + return (-1); + } + if (len != sizeof(tcpstat)) { + syslog(LOG_ERR, "net.inet.tcp.stats: wrong size"); + return (-1); + } + + len = sizeof(tcps_states); + if (sysctlbyname("net.inet.tcp.states", &tcps_states, &len, NULL, + 0) == -1) { + syslog(LOG_ERR, "net.inet.tcp.states: %m"); + return (-1); + } + if (len != sizeof(tcps_states)) { + syslog(LOG_ERR, "net.inet.tcp.states: wrong size"); + return (-1); + } + + tcp_stats_tick = get_ticks(); + + return (0); +} + +static int +fetch_tcp(void) +{ + size_t len; + struct xinpgen *ptr; + struct xtcpcb *tp; + struct tcp_index *oid; + in_addr_t inaddr; + + len = 0; + if (sysctlbyname("net.inet.tcp.pcblist", NULL, &len, NULL, 0) == -1) { + syslog(LOG_ERR, "net.inet.tcp.pcblist: %m"); + return (-1); + } + if (len > xinpgen_len) { + if ((ptr = realloc(xinpgen, len)) == NULL) { + syslog(LOG_ERR, "%zu: %m", len); + return (-1); + } + xinpgen = ptr; + xinpgen_len = len; + } + if (sysctlbyname("net.inet.tcp.pcblist", xinpgen, &len, NULL, 0) == -1) { + syslog(LOG_ERR, "net.inet.tcp.pcblist: %m"); + return (-1); + } + + tcp_tick = get_ticks(); + + tcp_total = 0; + for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len); + ptr->xig_len > sizeof(struct xinpgen); + ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) { + tp = (struct xtcpcb *)ptr; + if (tp->xt_inp.inp_gencnt > xinpgen->xig_gen || + (tp->xt_inp.inp_vflag & (INP_IPV4|INP_IPV6)) == 0) + continue; + + if (tp->xt_inp.inp_vflag & INP_IPV4) + tcp_total++; + } + + if (oidnum < tcp_total) { + oid = realloc(tcpoids, tcp_total * sizeof(tcpoids[0])); + if (oid == NULL) { + free(tcpoids); + oidnum = 0; + return (0); + } + tcpoids = oid; + oidnum = tcp_total; + } + + oid = tcpoids; + for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len); + ptr->xig_len > sizeof(struct xinpgen); + ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) { + tp = (struct xtcpcb *)ptr; + if (tp->xt_inp.inp_gencnt > xinpgen->xig_gen || + (tp->xt_inp.inp_vflag & INP_IPV4) == 0) + continue; + oid->tp = tp; + oid->index.len = 10; + inaddr = ntohl(tp->xt_inp.inp_laddr.s_addr); + oid->index.subs[0] = (inaddr >> 24) & 0xff; + oid->index.subs[1] = (inaddr >> 16) & 0xff; + oid->index.subs[2] = (inaddr >> 8) & 0xff; + oid->index.subs[3] = (inaddr >> 0) & 0xff; + oid->index.subs[4] = ntohs(tp->xt_inp.inp_lport); + inaddr = ntohl(tp->xt_inp.inp_faddr.s_addr); + oid->index.subs[5] = (inaddr >> 24) & 0xff; + oid->index.subs[6] = (inaddr >> 16) & 0xff; + oid->index.subs[7] = (inaddr >> 8) & 0xff; + oid->index.subs[8] = (inaddr >> 0) & 0xff; + oid->index.subs[9] = ntohs(tp->xt_inp.inp_fport); + oid++; + } + + qsort(tcpoids, tcp_total, sizeof(tcpoids[0]), tcp_compare); + + return (0); +} + +/* + * Scalars + */ +int +op_tcp(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + break; + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + abort(); + } + + if (tcp_stats_tick < this_tick) + if (fetch_tcp_stats() == -1) + return (SNMP_ERR_GENERR); + + switch (value->var.subs[sub - 1]) { + + case LEAF_tcpRtoAlgorithm: + value->v.integer = 4; /* Van Jacobson */ + break; + +#define hz clockinfo.hz + + case LEAF_tcpRtoMin: + value->v.integer = 1000 * TCPTV_MIN / hz; + break; + + case LEAF_tcpRtoMax: + value->v.integer = 1000 * TCPTV_REXMTMAX / hz; + break; +#undef hz + + case LEAF_tcpMaxConn: + value->v.integer = -1; + break; + + case LEAF_tcpActiveOpens: + value->v.uint32 = tcpstat.tcps_connattempt; + break; + + case LEAF_tcpPassiveOpens: + value->v.uint32 = tcpstat.tcps_accepts; + break; + + case LEAF_tcpAttemptFails: + value->v.uint32 = tcpstat.tcps_conndrops; + break; + + case LEAF_tcpEstabResets: + value->v.uint32 = tcpstat.tcps_drops; + break; + + case LEAF_tcpCurrEstab: + value->v.uint32 = tcps_states[TCPS_ESTABLISHED] + + tcps_states[TCPS_CLOSE_WAIT]; + break; + + case LEAF_tcpInSegs: + value->v.uint32 = tcpstat.tcps_rcvtotal; + break; + + case LEAF_tcpOutSegs: + value->v.uint32 = tcpstat.tcps_sndtotal - + tcpstat.tcps_sndrexmitpack; + break; + + case LEAF_tcpRetransSegs: + value->v.uint32 = tcpstat.tcps_sndrexmitpack; + break; + + case LEAF_tcpInErrs: + value->v.uint32 = tcpstat.tcps_rcvbadsum + + tcpstat.tcps_rcvbadoff + + tcpstat.tcps_rcvshort; + break; + } + return (SNMP_ERR_NOERROR); +} + +int +op_tcpconn(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + u_int i; + + if (tcp_tick < this_tick) + if (fetch_tcp() == -1) + return (SNMP_ERR_GENERR); + + switch (op) { + + case SNMP_OP_GETNEXT: + for (i = 0; i < tcp_total; i++) + if (index_compare(&value->var, sub, &tcpoids[i].index) < 0) + break; + if (i == tcp_total) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &tcpoids[i].index); + break; + + case SNMP_OP_GET: + for (i = 0; i < tcp_total; i++) + if (index_compare(&value->var, sub, &tcpoids[i].index) == 0) + break; + if (i == tcp_total) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + default: + abort(); + } + + switch (value->var.subs[sub - 1]) { + + case LEAF_tcpConnState: + switch (tcpoids[i].tp->t_state) { + + case TCPS_CLOSED: + value->v.integer = 1; + break; + case TCPS_LISTEN: + value->v.integer = 2; + break; + case TCPS_SYN_SENT: + value->v.integer = 3; + break; + case TCPS_SYN_RECEIVED: + value->v.integer = 4; + break; + case TCPS_ESTABLISHED: + value->v.integer = 5; + break; + case TCPS_CLOSE_WAIT: + value->v.integer = 8; + break; + case TCPS_FIN_WAIT_1: + value->v.integer = 6; + break; + case TCPS_CLOSING: + value->v.integer = 10; + break; + case TCPS_LAST_ACK: + value->v.integer = 9; + break; + case TCPS_FIN_WAIT_2: + value->v.integer = 7; + break; + case TCPS_TIME_WAIT: + value->v.integer = 11; + break; + default: + value->v.integer = 0; + break; + } + break; + + case LEAF_tcpConnLocalAddress: + value->v.ipaddress[0] = tcpoids[i].index.subs[0]; + value->v.ipaddress[1] = tcpoids[i].index.subs[1]; + value->v.ipaddress[2] = tcpoids[i].index.subs[2]; + value->v.ipaddress[3] = tcpoids[i].index.subs[3]; + break; + + case LEAF_tcpConnLocalPort: + value->v.integer = tcpoids[i].index.subs[4]; + break; + + case LEAF_tcpConnRemAddress: + value->v.ipaddress[0] = tcpoids[i].index.subs[5]; + value->v.ipaddress[1] = tcpoids[i].index.subs[6]; + value->v.ipaddress[2] = tcpoids[i].index.subs[7]; + value->v.ipaddress[3] = tcpoids[i].index.subs[8]; + break; + + case LEAF_tcpConnRemPort: + value->v.integer = tcpoids[i].index.subs[9]; + break; + } + return (SNMP_ERR_NOERROR); +} Property changes on: vendor/bsnmp/1.13/snmp_mibII/mibII_tcp.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/mibII_tree.def =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/mibII_tree.def (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/mibII_tree.def (revision 336778) @@ -0,0 +1,262 @@ +# +# Copyright (c) 2001-2003 +# Fraunhofer Institute for Open Communication Systems (FhG Fokus). +# All rights reserved. +# +# Author: Harti Brandt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Begemot: bsnmp/snmp_mibII/mibII_tree.def,v 1.13 2006/02/14 09:04:19 brandt_h Exp $ +# +# Definition of the standard interfaces and ip trees. +# +(1 internet + (2 mgmt + (1 mib2 + (2 interfaces + (1 ifNumber INTEGER op_interfaces GET) + (2 ifTable + (1 ifEntry : INTEGER op_ifentry + (1 ifIndex INTEGER GET) + (2 ifDescr OCTETSTRING GET) + (3 ifType INTEGER GET) + (4 ifMtu INTEGER32 GET) + (5 ifSpeed GAUGE GET) + (6 ifPhysAddress OCTETSTRING GET) + (7 ifAdminStatus INTEGER GET SET) + (8 ifOperStatus INTEGER GET) + (9 ifLastChange TIMETICKS GET) + (10 ifInOctets COUNTER GET) + (11 ifInUcastPkts COUNTER GET) + (12 ifInNUcastPkts COUNTER GET) + (13 ifInDiscards COUNTER GET) + (14 ifInErrors COUNTER GET) + (15 ifInUnknownProtos COUNTER GET) + (16 ifOutOctets COUNTER GET) + (17 ifOutUcastPkts COUNTER GET) + (18 ifOutNUcastPkts COUNTER GET) + (19 ifOutDiscards COUNTER GET) + (20 ifOutErrors COUNTER GET) + (21 ifOutQLen GAUGE GET) + (22 ifSpecific OID GET) + )) + ) + (4 ip + (1 ipForwarding INTEGER op_ip GET SET) + (2 ipDefaultTTL INTEGER op_ip GET SET) + (3 ipInReceives COUNTER op_ipstat GET) + (4 ipInHdrErrors COUNTER op_ipstat GET) + (5 ipInAddrErrors COUNTER op_ipstat GET) + (6 ipForwDatagrams COUNTER op_ipstat GET) + (7 ipInUnknownProtos COUNTER op_ipstat GET) + (8 ipInDiscards COUNTER op_ipstat GET) + (9 ipInDelivers COUNTER op_ipstat GET) + (10 ipOutRequests COUNTER op_ipstat GET) + (11 ipOutDiscards COUNTER op_ipstat GET) + (12 ipOutNoRoutes COUNTER op_ipstat GET) + (13 ipReasmTimeout INTEGER32 op_ipstat GET) + (14 ipReasmReqds COUNTER op_ipstat GET) + (15 ipReasmOKs COUNTER op_ipstat GET) + (16 ipReasmFails COUNTER op_ipstat GET) + (17 ipFragOKs COUNTER op_ipstat GET) + (18 ipFragFails COUNTER op_ipstat GET) + (19 ipFragCreates COUNTER op_ipstat GET) + (20 ipAddrTable + (1 ipAddrEntry : IPADDRESS op_ipaddr + (1 ipAdEntAddr IPADDRESS GET) + (2 ipAdEntIfIndex INTEGER GET SET) + (3 ipAdEntNetMask IPADDRESS GET SET) + (4 ipAdEntBcastAddr INTEGER GET SET) + (5 ipAdEntReasmMaxSize INTEGER GET) + )) + (22 ipNetToMediaTable + (1 ipNetToMediaEntry : INTEGER IPADDRESS op_nettomedia + (1 ipNetToMediaIfIndex INTEGER GET) + (2 ipNetToMediaPhysAddress OCTETSTRING GET) + (3 ipNetToMediaNetAddress IPADDRESS GET) + (4 ipNetToMediaType INTEGER GET) + )) + (23 ipRoutingDiscards INTEGER op_ipstat) # not available + (24 ipForward + (3 ipCidrRouteNumber GAUGE op_route GET) + (4 ipCidrRouteTable + (1 ipCidrRouteEntry : IPADDRESS IPADDRESS INTEGER IPADDRESS op_route_table + (1 ipCidrRouteDest IPADDRESS GET) + (2 ipCidrRouteMask IPADDRESS GET) + (3 ipCidrRouteTos INTEGER GET) + (4 ipCidrRouteNextHop IPADDRESS GET) + (5 ipCidrRouteIfIndex INTEGER GET) # SET + (6 ipCidrRouteType INTEGER GET) # SET + (7 ipCidrRouteProto INTEGER GET) + (8 ipCidrRouteAge INTEGER GET) + (9 ipCidrRouteInfo OID GET) # SET + (10 ipCidrRouteNextHopAS INTEGER GET) # SET + (11 ipCidrRouteMetric1 INTEGER GET) # SET + (12 ipCidrRouteMetric2 INTEGER GET) # SET + (13 ipCidrRouteMetric3 INTEGER GET) # SET + (14 ipCidrRouteMetric4 INTEGER GET) # SET + (15 ipCidrRouteMetric5 INTEGER GET) # SET + (16 ipCidrRouteStatus INTEGER GET) # SET + )) + ) + ) + (5 icmp + (1 icmpInMsgs COUNTER op_icmpstat GET) + (2 icmpInErrors COUNTER op_icmpstat GET) + (3 icmpInDestUnreachs COUNTER op_icmpstat GET) + (4 icmpInTimeExcds COUNTER op_icmpstat GET) + (5 icmpInParmProbs COUNTER op_icmpstat GET) + (6 icmpInSrcQuenchs COUNTER op_icmpstat GET) + (7 icmpInRedirects COUNTER op_icmpstat GET) + (8 icmpInEchos COUNTER op_icmpstat GET) + (9 icmpInEchoReps COUNTER op_icmpstat GET) + (10 icmpInTimestamps COUNTER op_icmpstat GET) + (11 icmpInTimestampReps COUNTER op_icmpstat GET) + (12 icmpInAddrMasks COUNTER op_icmpstat GET) + (13 icmpInAddrMaskReps COUNTER op_icmpstat GET) + (14 icmpOutMsgs COUNTER op_icmpstat GET) + (15 icmpOutErrors COUNTER op_icmpstat GET) + (16 icmpOutDestUnreachs COUNTER op_icmpstat GET) + (17 icmpOutTimeExcds COUNTER op_icmpstat GET) + (18 icmpOutParmProbs COUNTER op_icmpstat GET) + (19 icmpOutSrcQuenchs COUNTER op_icmpstat GET) + (20 icmpOutRedirects COUNTER op_icmpstat GET) + (21 icmpOutEchos COUNTER op_icmpstat GET) + (22 icmpOutEchoReps COUNTER op_icmpstat GET) + (23 icmpOutTimestamps COUNTER op_icmpstat GET) + (24 icmpOutTimestampReps COUNTER op_icmpstat GET) + (25 icmpOutAddrMasks COUNTER op_icmpstat GET) + (26 icmpOutAddrMaskReps COUNTER op_icmpstat GET) + ) + (6 tcp + (1 tcpRtoAlgorithm INTEGER op_tcp GET) + (2 tcpRtoMin INTEGER32 op_tcp GET) + (3 tcpRtoMax INTEGER32 op_tcp GET) + (4 tcpMaxConn INTEGER32 op_tcp GET) + (5 tcpActiveOpens COUNTER op_tcp GET) + (6 tcpPassiveOpens COUNTER op_tcp GET) + (7 tcpAttemptFails COUNTER op_tcp GET) + (8 tcpEstabResets COUNTER op_tcp GET) + (9 tcpCurrEstab GAUGE op_tcp GET) + (10 tcpInSegs COUNTER op_tcp GET) + (11 tcpOutSegs COUNTER op_tcp GET) + (12 tcpRetransSegs COUNTER op_tcp GET) + (13 tcpConnTable + (1 tcpConnEntry : IPADDRESS INTEGER IPADDRESS INTEGER op_tcpconn + (1 tcpConnState INTEGER GET) + (2 tcpConnLocalAddress IPADDRESS GET) + (3 tcpConnLocalPort INTEGER GET) + (4 tcpConnRemAddress IPADDRESS GET) + (5 tcpConnRemPort INTEGER GET) + )) + (14 tcpInErrs COUNTER op_tcp GET) + (15 tcpOutRsts COUNTER op_tcp) # don't know + ) + (7 udp + (1 udpInDatagrams COUNTER op_udp GET) + (2 udpNoPorts COUNTER op_udp GET) + (3 udpInErrors COUNTER op_udp GET) + (4 udpOutDatagrams COUNTER op_udp GET) + (5 udpTable + (1 udpEntry : IPADDRESS INTEGER op_udptable + (1 udpLocalAddress IPADDRESS GET) + (2 udpLocalPort INTEGER GET) + )) + ) + (31 ifMIB + (1 ifMIBObjects + (1 ifXTable + (1 ifXEntry : INTEGER op_ifxtable + (1 ifName OCTETSTRING GET) + (2 ifInMulticastPkts COUNTER GET) + (3 ifInBroadcastPkts COUNTER GET) + (4 ifOutMulticastPkts COUNTER GET) + (5 ifOutBroadcastPkts COUNTER GET) + (6 ifHCInOctets COUNTER64 GET) + (7 ifHCInUcastPkts COUNTER64 GET) + (8 ifHCInMulticastPkts COUNTER64 GET) + (9 ifHCInBroadcastPkts COUNTER64 GET) + (10 ifHCOutOctets COUNTER64 GET) + (11 ifHCOutUcastPkts COUNTER64 GET) + (12 ifHCOutMulticastPkts COUNTER64 GET) + (13 ifHCOutBroadcastPkts COUNTER64 GET) + (14 ifLinkUpDownTrapEnable INTEGER GET SET) + (15 ifHighSpeed GAUGE GET) + (16 ifPromiscuousMode INTEGER GET SET) + (17 ifConnectorPresent INTEGER GET) + (18 ifAlias OCTETSTRING GET) + (19 ifCounterDiscontinuityTime TIMETICKS GET) + )) + (2 ifStackTable + (1 ifStackEntry : INTEGER INTEGER op_ifstack + (1 ifStackHigherLayer INTEGER) + (2 ifStackLowerLayer INTEGER) + (3 ifStackStatus INTEGER GET) + )) + (4 ifRcvAddressTable + (1 ifRcvAddressEntry : INTEGER OCTETSTRING op_rcvaddr + (1 ifRcvAddressAddress OCTETSTRING) + (2 ifRcvAddressStatus INTEGER GET) + (3 ifRcvAddressType INTEGER GET) + )) + (5 ifTableLastChange TIMETICKS op_ifmib GET) + (6 ifStackLastChange TIMETICKS op_ifmib GET) + ) + ) + (48 ipMIB + ) + (49 tcpMIB + ) + (50 udpMIB + ) + )) + (4 private + (1 enterprises + (12325 fokus + (1 begemot + (3 begemotIp + (1 begemotIpObjects + (1 begemotMib2 + (1 begemotIfMaxspeed COUNTER64 op_begemot_mibII GET) + (2 begemotIfPoll TIMETICKS op_begemot_mibII GET) + (3 begemotIfForcePoll TIMETICKS op_begemot_mibII GET SET) + (4 begemotIfDataPoll TIMETICKS op_begemot_mibII GET SET) + ) + ) + ) + ) + ) + ) + ) + (6 snmpV2 + (3 snmpModules + (1 snmpMIB + (1 snmpMIBObjects + (5 snmpTraps + (3 linkDown OID op_snmp_trap) + (4 linkUp OID op_snmp_trap) + ) + ) + ) + )) +) Property changes on: vendor/bsnmp/1.13/snmp_mibII/mibII_tree.def ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/mibII_udp.c =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/mibII_udp.c (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/mibII_udp.c (revision 336778) @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmp_mibII/mibII_udp.c,v 1.7 2005/05/23 09:03:42 brandt_h Exp $ + * + * udp + */ +#include "mibII.h" +#include "mibII_oid.h" +#include +#include +#include +#include +#include + +struct udp_index { + struct asn_oid index; + struct xinpcb *inp; +}; + +static uint64_t udp_tick; +static struct udpstat udpstat; +static struct xinpgen *xinpgen; +static size_t xinpgen_len; +static u_int udp_total; + +static u_int oidnum; +static struct udp_index *udpoids; + +static int +udp_compare(const void *p1, const void *p2) +{ + const struct udp_index *t1 = p1; + const struct udp_index *t2 = p2; + + return (asn_compare_oid(&t1->index, &t2->index)); +} + +static int +fetch_udp(void) +{ + size_t len; + struct xinpgen *ptr; + struct xinpcb *inp; + struct udp_index *oid; + in_addr_t inaddr; + + len = sizeof(udpstat); + if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, NULL, 0) == -1) { + syslog(LOG_ERR, "net.inet.udp.stats: %m"); + return (-1); + } + if (len != sizeof(udpstat)) { + syslog(LOG_ERR, "net.inet.udp.stats: wrong size"); + return (-1); + } + + udp_tick = get_ticks(); + + len = 0; + if (sysctlbyname("net.inet.udp.pcblist", NULL, &len, NULL, 0) == -1) { + syslog(LOG_ERR, "net.inet.udp.pcblist: %m"); + return (-1); + } + if (len > xinpgen_len) { + if ((ptr = realloc(xinpgen, len)) == NULL) { + syslog(LOG_ERR, "%zu: %m", len); + return (-1); + } + xinpgen = ptr; + xinpgen_len = len; + } + if (sysctlbyname("net.inet.udp.pcblist", xinpgen, &len, NULL, 0) == -1) { + syslog(LOG_ERR, "net.inet.udp.pcblist: %m"); + return (-1); + } + + udp_total = 0; + for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len); + ptr->xig_len > sizeof(struct xinpgen); + ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) { + inp = (struct xinpcb *)ptr; + if (inp->inp_gencnt > xinpgen->xig_gen || + (inp->inp_vflag & INP_IPV4) == 0) + continue; + + udp_total++; + } + + if (oidnum < udp_total) { + oid = realloc(udpoids, udp_total * sizeof(udpoids[0])); + if (oid == NULL) { + free(udpoids); + oidnum = 0; + return (0); + } + udpoids = oid; + oidnum = udp_total; + } + + oid = udpoids; + for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len); + ptr->xig_len > sizeof(struct xinpgen); + ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) { + inp = (struct xinpcb *)ptr; + if (inp->inp_gencnt > xinpgen->xig_gen || + (inp->inp_vflag & INP_IPV4) == 0) + continue; + oid->inp = inp; + oid->index.len = 5; + inaddr = ntohl(inp->inp_laddr.s_addr); + oid->index.subs[0] = (inaddr >> 24) & 0xff; + oid->index.subs[1] = (inaddr >> 16) & 0xff; + oid->index.subs[2] = (inaddr >> 8) & 0xff; + oid->index.subs[3] = (inaddr >> 0) & 0xff; + oid->index.subs[4] = ntohs(inp->inp_lport); + oid++; + } + + qsort(udpoids, udp_total, sizeof(udpoids[0]), udp_compare); + + return (0); +} + +int +op_udp(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + break; + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + abort(); + } + + if (udp_tick < this_tick) + if (fetch_udp() == -1) + return (SNMP_ERR_GENERR); + + switch (value->var.subs[sub - 1]) { + + case LEAF_udpInDatagrams: + value->v.uint32 = udpstat.udps_ipackets; + break; + + case LEAF_udpNoPorts: + value->v.uint32 = udpstat.udps_noport + + udpstat.udps_noportbcast + + udpstat.udps_noportmcast; + break; + + case LEAF_udpInErrors: + value->v.uint32 = udpstat.udps_hdrops + + udpstat.udps_badsum + + udpstat.udps_badlen + + udpstat.udps_fullsock; + break; + + case LEAF_udpOutDatagrams: + value->v.uint32 = udpstat.udps_opackets; + break; + } + return (SNMP_ERR_NOERROR); +} + +int +op_udptable(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + u_int i; + + if (udp_tick < this_tick) + if (fetch_udp() == -1) + return (SNMP_ERR_GENERR); + + switch (op) { + + case SNMP_OP_GETNEXT: + for (i = 0; i < udp_total; i++) + if (index_compare(&value->var, sub, &udpoids[i].index) < 0) + break; + if (i == udp_total) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &udpoids[i].index); + break; + + case SNMP_OP_GET: + for (i = 0; i < udp_total; i++) + if (index_compare(&value->var, sub, &udpoids[i].index) == 0) + break; + if (i == udp_total) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + default: + abort(); + } + + switch (value->var.subs[sub - 1]) { + + case LEAF_udpLocalAddress: + value->v.ipaddress[0] = udpoids[i].index.subs[0]; + value->v.ipaddress[1] = udpoids[i].index.subs[1]; + value->v.ipaddress[2] = udpoids[i].index.subs[2]; + value->v.ipaddress[3] = udpoids[i].index.subs[3]; + break; + + case LEAF_udpLocalPort: + value->v.integer = udpoids[i].index.subs[4]; + break; + + } + return (SNMP_ERR_NOERROR); +} Property changes on: vendor/bsnmp/1.13/snmp_mibII/mibII_udp.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/snmp_mibII.3 =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/snmp_mibII.3 (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/snmp_mibII.3 (revision 336778) @@ -0,0 +1,368 @@ +.\" +.\" Copyright (c) 2004-2005 +.\" Hartmut Brandt +.\" All rights reserved. +.\" Copyright (c) 2001-2003 +.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus). +.\" All rights reserved. +.\" +.\" Author: Harti Brandt +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Begemot: bsnmp/snmp_mibII/snmp_mibII.3,v 1.10 2005/10/04 08:46:52 brandt_h Exp $ +.\" +.Dd January 4, 2017 +.Dt SNMP_MIBII 3 +.Os +.Sh NAME +.Nm mibII , +.Nm mibif_notify_f , +.Nm mib_netsock , +.Nm mib_if_set_dyn , +.Nm mib_refresh_iflist , +.Nm mib_find_if , +.Nm mib_find_if_sys , +.Nm mib_find_if_name , +.Nm mib_first_if , +.Nm mib_next_if , +.Nm mib_register_newif , +.Nm mib_unregister_newif , +.Nm mib_fetch_ifmib , +.Nm mib_if_admin , +.Nm mib_find_ifa , +.Nm mib_first_ififa , +.Nm mib_next_ififa , +.Nm mib_ifstack_create , +.Nm mib_ifstack_delete , +.Nm mib_find_rcvaddr , +.Nm mib_rcvaddr_create , +.Nm mib_rcvaddr_delete , +.Nm mibif_notify , +.Nm mibif_unnotify +.Nd "mib-2 module for bsnmpd." +.Sh LIBRARY +.Pq begemotSnmpdModulePath."mibII" = "@MODPATH@snmp_mibII.so" +.Sh SYNOPSIS +.In net/if.h +.In net/if_mib.h +.In bsnmp/snmpmod.h +.In bsnmp/snmp_mibII.h +.Ft typedef void +.Fn (*mibif_notify_f) "struct mibif *ifp" "enum mibif_notify event" "void *uarg" +.Vt extern int mib_netsock ; +.Ft void +.Fn mib_if_set_dyn "const char *ifname" +.Ft void +.Fn mib_refresh_iflist "void" +.Ft struct mibif * +.Fn mib_find_if "u_int ifindex" +.Ft struct mibif * +.Fn mib_find_if_sys "u_int sysindex" +.Ft struct mibif * +.Fn mib_find_if_name "const char *ifname" +.Ft struct mibif * +.Fn mib_first_if "void" +.Ft struct mibif * +.Fn mib_next_if "const struct mibif *ifp" +.Ft int +.Fn mib_register_newif "int (*func)(struct mibif *)" "const struct lmodule *mod" +.Ft void +.Fn mib_unregister_newif "const struct lmodule *mod" +.Ft int +.Fn mib_fetch_ifmib "struct mibif *ifp" +.Ft int +.Fn mib_if_admin "struct mibif *ifp" "int up" +.Ft struct mibifa * +.Fn mib_find_ifa "struct in_addr ipa" +.Ft struct mibifa * +.Fn mib_first_ififa "const struct mibif *ifp" +.Ft struct mibifa * +.Fn mib_next_ififa "struct mibifa *ifa" +.Ft int +.Fn mib_ifstack_create "const struct mibif *lower" "const struct mibif *upper" +.Ft void +.Fn mib_ifstack_delete "const struct mibif *lower" "const struct mibif *upper" +.Ft struct mibrcvaddr * +.Fn mib_find_rcvaddr "u_int ifindex" "const u_char *addr" "size_t addrlen" +.Ft struct mibrcvaddr * +.Fn mib_rcvaddr_create "struct mibif *ifp" "const u_char *addr" "size_t addrlen" +.Ft void +.Fn mib_rcvaddr_delete "struct mibrcvaddr *addr" +.Ft void * +.Fn mibif_notify "struct mibif *ifp" "const struct lmodule *mod" "mibif_notify_f func" "void *uarg" +.Ft void +.Fn mibif_unnotify "void *reg" +.Sh DESCRIPTION +The +.Nm snmp_mibII +module implements parts of the internet standard MIB-2. +Most of the relevant MIBs are implemented. +Some of the tables are restricted to be read-only instead of read-write. +The exact current implementation can be found in +.Pa @DEFPATH@mibII_tree.def . +The module also exports a number of functions and global variables for use +by other modules, that need to handle network interfaces. +This man page describes these functions. +.Ss DIRECT NETWORK ACCESS +The +.Nm +module opens a socket that is used to execute all network related +.Xr ioctl 2 +functions. +This socket is globally available under the name +.Va mib_netsock . +.Ss NETWORK INTERFACES +The +.Nm +module handles a list of all currently existing network interfaces. +It allows +other modules to handle their own interface lists with special information +by providing a mechanism to register to events that change the interface list +(see below). +The basic data structure is the interface structure: +.Bd -literal -offset indent +struct mibif { + TAILQ_ENTRY(mibif) link; + u_int flags; + u_int index; /* logical ifindex */ + u_int sysindex; + char name[IFNAMSIZ]; + char descr[256]; + struct ifmibdata mib; + uint64_t mibtick; + void *specmib; + size_t specmiblen; + u_char *physaddr; + u_int physaddrlen; + int has_connector; + int trap_enable; + uint64_t counter_disc; + mibif_notify_f xnotify; + void *xnotify_data; + const struct lmodule *xnotify_mod; + struct asn_oid spec_oid; +}; +.Ed +.Pp +The +.Nm +module tries to implement the semantic if +.Va ifIndex +as described in RFC-2863. +This RFC states, that an interface indexes may not be reused. +That means, for example, if +.Pa tun +is a synthetic interface type and the system creates the interface +.Pa tun0 , +destroys this interfaces and again creates a +.Pa tun 0 , +then these interfaces must have different interface indexes, because in fact +they are different interfaces. +If, on the other hand, there is a hardware interface +.Pa xl0 +and this interface disappears, because its driver is unloaded and appears +again, because the driver is loaded again, the interface index must stay +the same. +.Nm +implements this by differentiating between real and synthetic (dynamic) +interfaces. +An interface type can be declared dynamic by calling the function +.Fn mib_if_set_dyn +with the name if the interface type (for example +.Qq tun ). +For real interfaces, the module keeps the mapping between the interface name +and its +.Va ifIndex +in a special list, if the interface is unloaded. +For dynamic interfaces +a new +.Va ifIndex +is generated each time the interface comes into existence. +This means, that the interface index as seen by SNMP is not the same index +as used by the system. +The SNMP +.Va ifIndex +is held in field +.Va index , +the system's interface index is +.Va sysindex . +.Pp +A call to +.Nm mib_refresh_iflist +causes the entire interface list to be re-created. +.Pp +The interface list can be traversed with the functions +.Fn mib_first_if +and +.Fn mib_next_if . +Be sure not to change the interface list while traversing the list with +these two calls. +.Pp +There are three functions to find an interface by name or index. +.Fn mib_find_if +finds an interface by searching for an SNMP +.Va ifIndex , +.Fn mib_find_if_sys +finds an interface by searching for a system interface index and +.Fn mib_find_if_name +finds an interface by looking for an interface name. +Each of the function returns +.Li NULL +if the interface cannot be found. +.Pp +The function +.Fn mib_fetch_ifmib +causes the interface MIB to be refreshed from the kernel. +.Pp +The function +.Fn mib_if_admin +can be used to change the interface administrative state to up +(argument is 1) or down (argument is 0). +.Ss INTERFACE EVENTS +A module can register itself to receive a notification when a new entry is +created in the interface list. +This is done by calling +.Fn mib_register_newif . +A module can register only one function, a second call to +.Fn mib_register_newif +causes the registration to be overwritten. +The registration can be removed with a call to +.Fn mib_unregister_newif . +It is unregistered automatically, when the registering module is unloaded. +.Pp +A module can also register to events on a specific interface. +This is done by calling +.Fn mibif_notify . +This causes the given callback +.Fa func +to be called with the interface pointer, a notification code and +the user argument +.Fa uarg +when any of the following events occur: +.Bl -tag -width "XXXXX" +.It Li MIBIF_NOTIFY_DESTROY +The interface is destroyed. +.El +.Pp +This mechanism can be used to implement interface type specific MIB parts +in other modules. +The registration can be removed with +.Fn mib_unnotify +which the return value from +.Fa mib_notify . +Any notification registration is removed automatically when the interface +is destroyed or the registering module is unloaded. +.Em Note that only one module can register to any given interface . +.Ss INTERFACE ADDRESSES +The +.Nm +module handles a table of interface IP-addresses. +These addresses are held in a +.Bd -literal -offset indent +struct mibifa { + TAILQ_ENTRY(mibifa) link; + struct in_addr inaddr; + struct in_addr inmask; + struct in_addr inbcast; + struct asn_oid index; + u_int ifindex; + u_int flags; +}; +.Ed +.Pp +The (ordered) list of IP-addresses on a given interface can be traversed by +calling +.Fn mib_first_ififa +and +.Fn mib_next_ififa . +The list should not be considered read-only. +.Ss INTERFACE RECEIVE ADDRESSES +The internet MIB-2 contains a table of interface receive addresses. +These addresses are handled in: +.Bd -literal -offset indent +struct mibrcvaddr { + TAILQ_ENTRY(mibrcvaddr) link; + struct asn_oid index; + u_int ifindex; + u_char addr[ASN_MAXOIDLEN]; + size_t addrlen; + u_int flags; +}; +enum { + MIBRCVADDR_VOLATILE = 0x00000001, + MIBRCVADDR_BCAST = 0x00000002, + MIBRCVADDR_HW = 0x00000004, +}; +.Ed +.Pp +Note, that the assignment of +.Li MIBRCVADDR_BCAST +is based on a list of known interface types. +The flags should be handled +by modules implementing interface type specific MIBs. +.Pp +A receive address can be created with +.Fn mib_rcvaddr_create +and deleted with +.Fn mib_rcvaddr_delete . +This needs to be done only for addresses that are not automatically handled +by the system. +.Pp +A receive address can be found with +.Fn mib_find_rcvaddr . +.Ss INTERFACE STACK TABLE +The +.Nm +module maintains also the interface stack table. +Because for complex stacks, +there is no system supported generic way of getting this information, interface +type specific modules need to help setting up stack entries. +The +.Nm +module handles only the top and bottom entries. +.Pp +A table entry is created with +.Fn mib_ifstack_create +and deleted with +.Fn mib_ifstack_delete . +Both functions need the pointers to the interfaces. +Entries are automatically +deleted if any of the interfaces of the entry is destroyed. +The functions handle +both the stack table and the reverse stack table. +.Sh FILES +.Bl -tag -width ".It Pa @DEFPATH@mibII_tree.def" -compact +.It Pa @DEFPATH@mibII_tree.def +The description of the MIB tree implemented by +.Nm . +.It Pa /usr/local/share/snmp/mibs +.It Pa @MIBSPATH@ +The various internet MIBs. +.El +.Sh SEE ALSO +.Xr gensnmptree 1 , +.Xr snmpmod 3 +.Sh STANDARDS +This implementation conforms to the applicable IETF RFCs. +.Sh AUTHORS +.An Hartmut Brandt Aq harti@FreeBSD.org Property changes on: vendor/bsnmp/1.13/snmp_mibII/snmp_mibII.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_mibII/snmp_mibII.h =================================================================== --- vendor/bsnmp/1.13/snmp_mibII/snmp_mibII.h (nonexistent) +++ vendor/bsnmp/1.13/snmp_mibII/snmp_mibII.h (revision 336778) @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmp_mibII/snmp_mibII.h,v 1.18 2006/02/14 09:04:19 brandt_h Exp $ + * + * Implementation of the interfaces and IP groups of MIB-II. + */ +#ifndef snmp_mibII_h_ +#define snmp_mibII_h_ + +/* forward declaration */ +struct mibif; + +enum mibif_notify { + MIBIF_NOTIFY_DESTROY +}; + +typedef void (*mibif_notify_f)(struct mibif *, enum mibif_notify, void *); + +/* + * Interfaces. This structure describes one interface as seen in the MIB. + * Interfaces are indexed by ifindex. This is not the same as the index + * used by the system because of the rules in RFC-2863 section 3.1.5. This + * RFC requires, that an ifindex is not to be re-used for ANOTHER dynamically + * interfaces once the interface was deleted. The system's ifindex is in + * sysindex. Mapping is via the mapping table below. + */ +struct mibif { + TAILQ_ENTRY(mibif) link; + u_int flags; + u_int index; /* the logical ifindex */ + u_int sysindex; + char name[IFNAMSIZ]; + char descr[256]; + struct ifmibdata mib; + uint64_t mibtick; + void *specmib; + size_t specmiblen; + u_char *physaddr; + u_int physaddrlen; + int has_connector; + int trap_enable; + uint64_t counter_disc; + + /* + * This is needed to handle interface type specific information + * in sub-modules. It contains a function pointer which handles + * notifications and a data pointer to arbitrary data. + * Should be set via the mibif_notify function. + */ + mibif_notify_f xnotify; + void *xnotify_data; + const struct lmodule *xnotify_mod; + + /* to be set by ifType specific modules. This is ifSpecific. */ + struct asn_oid spec_oid; + + /* private data - don't touch */ + void *private; +}; + +/* + * Interface IP-address table. + */ +struct mibifa { + TAILQ_ENTRY(mibifa) link; + struct in_addr inaddr; + struct in_addr inmask; + struct in_addr inbcast; + struct asn_oid index; /* index for table search */ + u_int ifindex; + u_int flags; +}; + +/* + * Interface receive addresses. Interface link-level multicast, broadcast + * and hardware addresses are handled automatically. + */ +struct mibrcvaddr { + TAILQ_ENTRY(mibrcvaddr) link; + struct asn_oid index; + u_int ifindex; + u_char addr[ASN_MAXOIDLEN]; + size_t addrlen; + u_int flags; +}; +enum { + MIBRCVADDR_VOLATILE = 0x00000001, + MIBRCVADDR_BCAST = 0x00000002, + MIBRCVADDR_HW = 0x00000004, +}; + +/* network socket */ +extern int mib_netsock; + +/* set an interface name to dynamic mode */ +void mib_if_set_dyn(const char *); + +/* re-read the systems interface list */ +void mib_refresh_iflist(void); + +/* find interface by index */ +struct mibif *mib_find_if(u_int); +struct mibif *mib_find_if_sys(u_int); +struct mibif *mib_find_if_name(const char *); + +/* iterate through all interfaces */ +struct mibif *mib_first_if(void); +struct mibif *mib_next_if(const struct mibif *); + +/* register for interface creations */ +int mib_register_newif(int (*)(struct mibif *), const struct lmodule *); +void mib_unregister_newif(const struct lmodule *); + +/* get fresh MIB data */ +int mib_fetch_ifmib(struct mibif *); + +/* change the ADMIN status of an interface and refresh the MIB */ +int mib_if_admin(struct mibif *, int up); + +/* find interface address by address */ +struct mibifa *mib_find_ifa(struct in_addr); + +/* find first/next address for a given interface */ +struct mibifa *mib_first_ififa(const struct mibif *); +struct mibifa *mib_next_ififa(struct mibifa *); + +/* create/delete stacking entries */ +int mib_ifstack_create(const struct mibif *lower, const struct mibif *upper); +void mib_ifstack_delete(const struct mibif *lower, const struct mibif *upper); + +/* find receive address */ +struct mibrcvaddr *mib_find_rcvaddr(u_int, const u_char *, size_t); + +/* create/delete receive addresses */ +struct mibrcvaddr *mib_rcvaddr_create(struct mibif *, const u_char *, size_t); +void mib_rcvaddr_delete(struct mibrcvaddr *); + +/* register for interface notification */ +void *mibif_notify(struct mibif *, const struct lmodule *, mibif_notify_f, + void *); +void mibif_unnotify(void *); + +#endif Property changes on: vendor/bsnmp/1.13/snmp_mibII/snmp_mibII.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_ntp/BEGEMOT-NTP-MIB.txt =================================================================== --- vendor/bsnmp/1.13/snmp_ntp/BEGEMOT-NTP-MIB.txt (nonexistent) +++ vendor/bsnmp/1.13/snmp_ntp/BEGEMOT-NTP-MIB.txt (revision 336778) @@ -0,0 +1,144 @@ +-- +-- Copyright (c) 2005 +-- Hartmut Brandt +-- All rights reserved. +-- +-- Author: Harti Brandt +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- 1. Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- 2. Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +-- ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +-- SUCH DAMAGE. +-- +-- $Begemot: bsnmp/snmp_ntp/BEGEMOT-NTP-MIB.txt,v 1.3 2005/10/04 08:13:41 brandt_h Exp $ +-- +-- Private MIB for NTP module. +-- +BEGEMOT-NTP-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, TimeTicks, Unsigned32, Counter64 + FROM SNMPv2-SMI + TruthValue + FROM SNMPv2-TC + begemot + FROM BEGEMOT-MIB; + +begemotNtp MODULE-IDENTITY + LAST-UPDATED "200509300000Z" + ORGANIZATION "German Aerospace Center" + CONTACT-INFO + " Hartmut Brandt + + Postal: German Aerospace Center + Oberpfaffenhofen + 82234 Wessling + Germany + + Fax: +49 8153 28 2843 + + E-mail: harti@freebsd.org" + DESCRIPTION + "The MIB for the NTP control module for SNMP." + ::= { begemot 201 } + +begemotNtpObjects OBJECT IDENTIFIER ::= { begemotNtp 1 } + +begemotNtpHost OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The name of the host where the NTP daemon is running that + is to be connected." + ::= { begemotNtpObjects 1 } + +begemotNtpPort OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The port of the host where the NTP daemon is running that + is to be connected." + ::= { begemotNtpObjects 2 } + +begemotNtpTimeout OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The number of ticks to wait for the response from the NTP + daemon to complete." + ::= { begemotNtpObjects 3 } + +begemotNtpDebug OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Debug flags. The following flags are currently used: + + 0x01 - produce a dump of all received/sent NTP packets. + 0x02 - print the variable names and values return by the daemon + + Other bits are ignored." + ::= { begemotNtpObjects 4 } + +begemotNtpJitter OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Current jitter in seconds multiplied by 2^32." + ::= { begemotNtpObjects 5 } + +begemotNtpStability OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Current stability in ppm multiplied by 2^32." + ::= { begemotNtpObjects 6 } + +begemotNtpJitterThresh OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Jitter trap threshold in seconds multiplied by 2^32." + ::= { begemotNtpObjects 7 } + +begemotNtpStabilityThresh OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Stability trap threshold in ppm multiplied by 2^32." + ::= { begemotNtpObjects 8 } + +begemotNtpTrapEnable OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Enables the sending of traps when either the peer is lost/ + found or one of the above thresholds is crossed." + ::= { begemotNtpObjects 9 } + +END Property changes on: vendor/bsnmp/1.13/snmp_ntp/BEGEMOT-NTP-MIB.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_ntp/Makefile.in =================================================================== --- vendor/bsnmp/1.13/snmp_ntp/Makefile.in (nonexistent) +++ vendor/bsnmp/1.13/snmp_ntp/Makefile.in (revision 336778) @@ -0,0 +1,38 @@ +# Copyright (c) 2005 +# Hartmut Brandt. +# All rights reserved. +# +# Author: Harti Brandt +# +# $Begemot: bsnmp/trunk/snmp_ntp/Makefile.in 1487 2008-12-23 19:03:33Z brandt_h $ +# +MOD= ntp +SRCS= ${MOD}_tree.c snmp_ntp.c +DEFS= ntp_tree.def +BMIBS= BEGEMOT-NTP-MIB.txt NTP-MIB.txt NTP-PROXY-MIB.txt +# MAN3= snmp_ntp.3 +MANFILTER= sed -e 's%@MODPATH@%${LIBDIR}/%g' \ + -e 's%@DEFPATH@%${DEFSDIR}/%g' \ + -e 's%@MIBSPATH@%${MIBSDIR}/%g' + +XSYM= ntpMIB + +LIB= snmp_${MOD}.la +SHLIB_MAJOR= 3 +SHLIB_MINOR= 0 + +CFLAGS+= -I$(srcdir) -I$(srcdir)/../lib -I$(builddir) -I$(srcdir)/../snmpd + +CLEANFILES += ${MOD}_oid.h ${MOD}_tree.c ${MOD}_tree.h + +# for bootstrapping +GENSNMPTREE= $(builddir)/../gensnmptree/gensnmptree -I${srcdir}/../lib + +$(LIB): ${MOD}_oid.h ${MOD}_tree.h $(SRCS:.c=.lo) + $(LIBTOOL) --mode=link $(CC) $(LDLAGS) -module -o $@ $(SRCS:.c=.lo) -rpath $(libdir) -version-info $(SHLIB_MAJOR):$(SHLIB_MINOR) + +${MOD}_oid.h: ${MOD}_tree.def + ${GENSNMPTREE} <${srcdir}/${MOD}_tree.def -e ${XSYM} >$@ + +${MOD}_tree.h ${MOD}_tree.c : ${MOD}_tree.def + ${GENSNMPTREE} <${srcdir}/${MOD}_tree.def -l -p ${MOD}_ Property changes on: vendor/bsnmp/1.13/snmp_ntp/Makefile.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_ntp/NTP-MIB.txt =================================================================== --- vendor/bsnmp/1.13/snmp_ntp/NTP-MIB.txt (nonexistent) +++ vendor/bsnmp/1.13/snmp_ntp/NTP-MIB.txt (revision 336778) @@ -0,0 +1,627 @@ +-- +-- NTP MIB, Revision 0.2, 7/25/97 +-- + +NTP-MIB DEFINITIONS ::= BEGIN + +IMPORTS + Integer32, IpAddress, MODULE-IDENTITY, OBJECT-TYPE, Unsigned32, + enterprises + FROM SNMPv2-SMI + + TEXTUAL-CONVENTION, TruthValue + FROM SNMPv2-TC; + +ntpMIB MODULE-IDENTITY + LAST-UPDATED "199707251530Z" + ORGANIZATION + "University of Delaware" + CONTACT-INFO + "Adarsh Sethi + Department of Computer & Information Sciences + University of Delaware + Newark, DE 19716 + Tel: +1 302 831 1945 + E-mail: sethi@cis.udel.edu + + David Mills + Department of Electrical Engineering + University of Delaware + Newark, DE 19716 + Tel: +1 302 831 ???? + E-mail: mills@ee.udel.edu" + DESCRIPTION + "This MIB module defines a MIB which provides mechanisms to + monitor and control an NTP server." + ::= { udel 3 } + +-- +-- Position within the OID hierarchy of this MIB: +-- +udel OBJECT IDENTIFIER + ::= { enterprises 1277 } + +-- +-- The various groups defined within this MIB definition: +-- +ntpSystem OBJECT IDENTIFIER + ::= { ntpMIB 1 } + +ntpPeers OBJECT IDENTIFIER + ::= { ntpMIB 2 } + +ntpFilter OBJECT IDENTIFIER + ::= { ntpMIB 3 } + +-- +-- Textual conventions: +-- + +NTPTimeStamp ::= TEXTUAL-CONVENTION + DISPLAY-HINT "4x.4x" + STATUS current + DESCRIPTION + "" + SYNTAX OCTET STRING (SIZE(8)) + +NTPLeapIndicator ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "" + SYNTAX INTEGER { + noWarning(0), + addSecond(1), + subtractSecond(2), + alarm(3) } + +-- +-- System Group +-- + +ntpSysLeap OBJECT-TYPE + SYNTAX NTPLeapIndicator + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " two-bit code warning of an impending leap + second to be inserted in the NTP timescale." + ::= { ntpSystem 1 } + +ntpSysStratum OBJECT-TYPE + SYNTAX Integer32 (0..255) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " indicating the stratum of the local clock. + 0, unspecified + 1, primary reference (e.g.,, calibrated atomic clock, + radio clock) + 2-255, secondary reference (via NTP)" + ::= { ntpSystem 2 } + +ntpSysPrecision OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "signed integer indicating the precision + of the various clocks, in seconds to the nearest power + of two." + ::= { ntpSystem 3 } + +ntpSysRootDelay OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "the total roundtrip delay to the primary + reference source at the root of the synchronization + subnet, in seconds" + ::= { ntpSystem 4 } + +ntpSysRootDispersion OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "the maximum error relative to the primary + reference source at the root of the synchronization + subnet, in seconds. Only positive values greater + than zero are possible" + ::= { ntpSystem 5 } + +ntpSysRefId OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " the particular reference clock. In the case of + stratum 0 (unspecified) or stratum 1 (primary reference + source), this is a four-octet, left-justified,zero-padded + ASCII string.In the case of stratum 2 and greater (secondary + reference) this is the four-octet Internet address of the + peer selected for synchronization." + ::= { ntpSystem 6 } + +ntpSysRefTime OBJECT-TYPE + SYNTAX NTPTimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " the local time when the local clock was last + updated. If the local clock has neverbeen synchronized, + the value is zero." + ::= { ntpSystem 7 } + +ntpSysPoll OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " the minimum interval between transmitted + messages, in seconds as a power of two. For instance, + a value of six indicates a minimum interval of 64 seconds." + ::= { ntpSystem 8 } + +ntpSysPeer OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " the current synchronization source. Usually + this will be a pointer to a structure containing the peer + variables. The special value NULL indicates there is no + currently valid synchronization source." + ::= { ntpSystem 9 } + +ntpSysPhase OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpSystem 10 } + +ntpSysFreq OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpSystem 11 } + +ntpSysError OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpSystem 12 } + +ntpSysClock OBJECT-TYPE + SYNTAX NTPTimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "the current local time. Local time is derived + from the hardware clock of the particular machine and + increments at intervals depending on the design used." + ::= { ntpSystem 13 } + +ntpSysSystem OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " the type of the local Operating System" + ::= { ntpSystem 14 } + +ntpSysProcessor OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " the type of the local Processor" + ::= { ntpSystem 15 } + +-- +-- Peers Group +-- + +-- +-- Peer Variables Table +-- + +ntpPeersVarTable OBJECT-TYPE + SYNTAX SEQUENCE OF NtpPeersVarEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + ::= { ntpPeers 1 } + +ntpPeersVarEntry OBJECT-TYPE + SYNTAX NtpPeersVarEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + INDEX { ntpPeersAssocId } + ::= { ntpPeersVarTable 1 } + +NtpPeersVarEntry ::= SEQUENCE { + ntpPeersAssocId Unsigned32, + ntpPeersConfigured TruthValue, + ntpPeersPeerAddress IpAddress, + ntpPeersPeerPort Unsigned32, + ntpPeersHostAddress IpAddress, + ntpPeersHostPort Unsigned32, + ntpPeersLeap NTPLeapIndicator, + ntpPeersMode INTEGER, + ntpPeersStratum Integer32, + ntpPeersPeerPoll Integer32, + ntpPeersHostPoll Integer32, + ntpPeersPrecision Integer32, + ntpPeersRootDelay OCTET STRING, + ntpPeersRootDispersion OCTET STRING, + ntpPeersRefId OCTET STRING, + ntpPeersRefTime NTPTimeStamp, + ntpPeersOrgTime NTPTimeStamp, + ntpPeersReceiveTime NTPTimeStamp, + ntpPeersTransmitTime NTPTimeStamp, + ntpPeersUpdateTime NTPTimeStamp, + ntpPeersReach Unsigned32, + ntpPeersTimer Integer32, + ntpPeersOffset OCTET STRING, + ntpPeersDelay OCTET STRING, + ntpPeersDispersion OCTET STRING +} + +ntpPeersAssocId OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + ::= { ntpPeersVarEntry 1 } + +ntpPeersConfigured OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " This is a bit indicating that the association + was created from configuration information and should not + be demobilized if the peer becomes unreachable." + ::= { ntpPeersVarEntry 2 } + +ntpPeersPeerAddress OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " the Internet address of the peer" + ::= { ntpPeersVarEntry 3 } + +ntpPeersPeerPort OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " 16-bit port number of the peer." + ::= { ntpPeersVarEntry 4 } + +ntpPeersHostAddress OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " the Internet address of the host" + ::= { ntpPeersVarEntry 5 } + +ntpPeersHostPort OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " 16-bit port number of the host" + ::= { ntpPeersVarEntry 6 } + +ntpPeersLeap OBJECT-TYPE + SYNTAX NTPLeapIndicator + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " two-bit code warning of an impending leap + second to be inserted in the NTP timescale." + ::= { ntpPeersVarEntry 7 } + +ntpPeersMode OBJECT-TYPE + SYNTAX INTEGER { + unspecified(0), + symmetricActive(1), + symmetricPassive(2), + client(3), + server(4), + broadcast(5), + reservedControl(6), + reservedPrivate(7) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " the association mode,with values coded as + follows: + 0, unspecified + 1, symmetric active + 2, symmetric passive + 3, client + 4, server + 5, broadcast + 6, reserved for NTP control messages + 7, reserved for private use + " + ::= { ntpPeersVarEntry 8 } + +ntpPeersStratum OBJECT-TYPE + SYNTAX Integer32 (0..255) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " indicating the stratum of the peer clock. + 0, unspecified + 1, primary reference (e.g.,, calibrated atomic clock, + radio clock) + 2-255, secondary reference (via NTP)" + ::= { ntpPeersVarEntry 9 } + +ntpPeersPeerPoll OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "poll interval of the peer" + ::= { ntpPeersVarEntry 10 } + +ntpPeersHostPoll OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "poll interval of the host" + ::= { ntpPeersVarEntry 11 } + +ntpPeersPrecision OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "the same as the systemPrecision except this is + for the peer" + ::= { ntpPeersVarEntry 12 } + +ntpPeersRootDelay OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "the same as the systemRootDealy except this is for + the peer" + ::= { ntpPeersVarEntry 13 } + +ntpPeersRootDispersion OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "the same as the systemDispersion except this is for + the peer" + ::= { ntpPeersVarEntry 14 } + +ntpPeersRefId OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "the same as the systemRefid except this is for + the peer" + ::= { ntpPeersVarEntry 15 } + +ntpPeersRefTime OBJECT-TYPE + SYNTAX NTPTimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "the same as the systemRefTime except this is for + the peer" + ::= { ntpPeersVarEntry 16 } + +ntpPeersOrgTime OBJECT-TYPE + SYNTAX NTPTimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " the local time at the peer when its latest + NTP message was sent. If the peer becomes unreachable the + value is set to zero." + ::= { ntpPeersVarEntry 17 } + +ntpPeersReceiveTime OBJECT-TYPE + SYNTAX NTPTimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "the local time when the latest NTP message + from the peer arrived. If the peer becomes unreachable the + value is set to zero." + ::= { ntpPeersVarEntry 18 } + +ntpPeersTransmitTime OBJECT-TYPE + SYNTAX NTPTimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "the local time at which the NTP message + departed the sender." + ::= { ntpPeersVarEntry 19 } + +ntpPeersUpdateTime OBJECT-TYPE + SYNTAX NTPTimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " " + ::= { ntpPeersVarEntry 20 } + +ntpPeersReach OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "a shift register of NTP.WINDOW bits used to determine + the reachability status of the peer, with bits entering + from the least significant (rightmost) end. A peer is + considered reachable if at least one bit in this register is + set to one." + ::= { ntpPeersVarEntry 21 } + +ntpPeersTimer OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpPeersVarEntry 22 } + +ntpPeersOffset OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpPeersVarEntry 23 } + +ntpPeersDelay OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpPeersVarEntry 24 } + +ntpPeersDispersion OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpPeersVarEntry 25 } + +-- +-- Filter Group +-- +-- Implementation of this group is optional. It must be implemented +-- when the filter and selection algorithms described in Section 4 +-- of RFC 1305 are used. +-- + +-- +-- Filter Group Peer Variables Table +-- +ntpFilterPeersVarTable OBJECT-TYPE + SYNTAX SEQUENCE OF NtpFilterPeersVarEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "This table is an extension of the Peer Variables Table + in the Peer Group." + ::= { ntpFilter 1 } + +ntpFilterPeersVarEntry OBJECT-TYPE + SYNTAX NtpFilterPeersVarEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + AUGMENTS { ntpPeersVarEntry } + ::= { ntpFilterPeersVarTable 1 } + +NtpFilterPeersVarEntry ::= SEQUENCE { + ntpFilterValidEntries Integer32 +} + +ntpFilterValidEntries OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of valid entries for a peer in the Filter Register Table." + ::= { ntpFilterPeersVarEntry 1 } + +-- +-- Filter Register Table +-- + +ntpFilterRegisterTable OBJECT-TYPE + SYNTAX SEQUENCE OF NtpFilterRegisterEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + ::= { ntpFilter 2 } + +ntpFilterRegisterEntry OBJECT-TYPE + SYNTAX NtpFilterRegisterEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + INDEX { ntpPeersAssocId, ntpFilterIndex } + ::= { ntpFilterRegisterTable 1 } + +NtpFilterRegisterEntry ::= SEQUENCE { + ntpFilterIndex Unsigned32, + ntpFilterPeersOffset OCTET STRING, + ntpFilterPeersDelay OCTET STRING, + ntpFilterPeersDispersion OCTET STRING +} + +ntpFilterIndex OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + ::= { ntpFilterRegisterEntry 1 } + +ntpFilterPeersOffset OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "the offset of the peer clock relative to the + local clock in seconds" + ::= { ntpFilterRegisterEntry 2 } + +ntpFilterPeersDelay OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "roundtrip delay of the peer clock relative to the + local clock over the network path between them, in seconds. + this variable can take on both positive and negative values, + depending on clock precision and skew-error accumulation." + ::= { ntpFilterRegisterEntry 3 } + +ntpFilterPeersDispersion OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "the maximum error of the peer clock relative to the + local clock over the network path between them, in seconds. + Only positive values greater than zero are possible." + ::= { ntpFilterRegisterEntry 4 } + +END Property changes on: vendor/bsnmp/1.13/snmp_ntp/NTP-MIB.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_ntp/NTP-PROXY-MIB.txt =================================================================== --- vendor/bsnmp/1.13/snmp_ntp/NTP-PROXY-MIB.txt (nonexistent) +++ vendor/bsnmp/1.13/snmp_ntp/NTP-PROXY-MIB.txt (revision 336778) @@ -0,0 +1,616 @@ +-- +-- NTP Proxy MIB, Revision 0.2, 7/25/97 +-- + +NTP-PROXY-MIB DEFINITIONS ::= BEGIN + +IMPORTS + NTPLeapIndicator, NTPTimeStamp + FROM NTP-MIB + + Integer32, IpAddress, MODULE-IDENTITY, OBJECT-TYPE, Unsigned32, + enterprises + FROM SNMPv2-SMI + + TEXTUAL-CONVENTION, TruthValue + FROM SNMPv2-TC; + +ntpProxyMIB MODULE-IDENTITY + LAST-UPDATED "199707251540Z" + ORGANIZATION + "University of Delaware" + CONTACT-INFO + "Adarsh Sethi + Department of Computer & Information Sciences + University of Delaware + Newark, DE 19716 + Tel: +1 302 831 1945 + E-mail: sethi@cis.udel.edu + + David Mills + Department of Electrical Engineering + University of Delaware + Newark, DE 19716 + Tel: +1 302 831 ???? + E-mail: mills@ee.udel.edu" + DESCRIPTION + "This MIB module defines a MIB which provides mechanisms to + monitor and control many NTP servers via a Proxy Agent." + ::= { enterprises 1277 4 } + +-- +-- The position within the OID hierarchy of this MIB: +-- + +udel OBJECT IDENTIFIER + ::= { enterprises 1277 } + +-- +-- The various groups defined within this MIB definition: +-- + +ntpProxyControl OBJECT IDENTIFIER + ::= { ntpProxyMIB 1 } + +-- +-- Textual conventions: +-- + +NTPRowStatus ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "The NTPRowStatus textual convention is modeled after the + RowStatus textual convention of RFC 1903, but is simpler + because it only allows one create operation (the create- + and-go of RowStatus) and does not allow row deletion. If + the state of the status column is `notInService' and the + management station tries to set it to `create', the + corresponding row is created and the operation is successful. + If the set to `create' is attempted when the status column + is in state `active', the operation fails and inconsistentValue + is returned. A management station is not permitted to delete + the conceptual row; deletion is carried out by the agent + in an autonomous manner." + SYNTAX INTEGER { + -- the following values are states: + -- these values may be read, but not written + active(1), + notInService(2), + -- the following value is an action: + -- this value may be written, but is never read + create(3) + } + +-- +-- Control group +-- + +-- +-- ProxyControl Table +-- + +ntpProxyControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF NtpProxyControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + ::= { ntpProxyControl 1 } + +ntpProxyControlEntry OBJECT-TYPE + SYNTAX NtpProxyControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + INDEX { ntpProxyServerIPAddr } + ::= { ntpProxyControlTable 1 } + +NtpProxyControlEntry ::= SEQUENCE { + ntpProxyServerIPAddr IpAddress, + ntpProxyControlStatus NTPRowStatus +} + +ntpProxyServerIPAddr OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + ::= { ntpProxyControlEntry 1 } + +ntpProxyControlStatus OBJECT-TYPE + SYNTAX NTPRowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "" + ::= { ntpProxyControlEntry 2 } + +-- +-- Proxy Server System Table +-- + +ntpProxyServerSystemTable OBJECT-TYPE + SYNTAX SEQUENCE OF NtpProxyServerSystemEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + ::= { ntpProxyControl 2 } + +ntpProxyServerSystemEntry OBJECT-TYPE + SYNTAX NtpProxyServerSystemEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + INDEX { ntpProxyServerIPAddr } + ::= { ntpProxyServerSystemTable 1 } + +NtpProxyServerSystemEntry ::= SEQUENCE { + ntpProxyServerSysLeap NTPLeapIndicator, + ntpProxyServerSysStratum Integer32, + ntpProxyServerSysPrecision Integer32, + ntpProxyServerSysRootDelay OCTET STRING, + ntpProxyServerSysRootDispersion OCTET STRING, + ntpProxyServerSysRefId OCTET STRING, + ntpProxyServerSysRefTime NTPTimeStamp, + ntpProxyServerSysPoll Integer32, + ntpProxyServerSysPeer Unsigned32, + ntpProxyServerSysPhase OCTET STRING, + ntpProxyServerSysFreq OCTET STRING, + ntpProxyServerSysError OCTET STRING, + ntpProxyServerSysClock NTPTimeStamp, + ntpProxyServerSysSystem OCTET STRING, + ntpProxyServerSysProcessor OCTET STRING +} + +ntpProxyServerSysLeap OBJECT-TYPE + SYNTAX NTPLeapIndicator + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyServerSystemEntry 1 } + +ntpProxyServerSysStratum OBJECT-TYPE + SYNTAX Integer32 (0..255) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyServerSystemEntry 2 } + +ntpProxyServerSysPrecision OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyServerSystemEntry 3 } + +ntpProxyServerSysRootDelay OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyServerSystemEntry 4 } + +ntpProxyServerSysRootDispersion OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyServerSystemEntry 5 } + +ntpProxyServerSysRefId OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyServerSystemEntry 6 } + +ntpProxyServerSysRefTime OBJECT-TYPE + SYNTAX NTPTimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyServerSystemEntry 7 } + +ntpProxyServerSysPoll OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyServerSystemEntry 8 } + +ntpProxyServerSysPeer OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyServerSystemEntry 9 } + +ntpProxyServerSysPhase OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyServerSystemEntry 10 } + +ntpProxyServerSysFreq OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyServerSystemEntry 11 } + +ntpProxyServerSysError OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyServerSystemEntry 12 } + +ntpProxyServerSysClock OBJECT-TYPE + SYNTAX NTPTimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyServerSystemEntry 13 } + +ntpProxyServerSysSystem OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyServerSystemEntry 14 } + +ntpProxyServerSysProcessor OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyServerSystemEntry 15 } + +-- +-- Proxy Peer Variables Table +-- +ntpProxyPeersVarTable OBJECT-TYPE + SYNTAX SEQUENCE OF NtpProxyPeersVarEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + ::= { ntpProxyControl 3 } + +ntpProxyPeersVarEntry OBJECT-TYPE + SYNTAX NtpProxyPeersVarEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + INDEX { ntpProxyServerIPAddr, ntpProxyPeersAssocId } + ::= { ntpProxyPeersVarTable 1 } + +NtpProxyPeersVarEntry ::= SEQUENCE { + ntpProxyPeersAssocId Unsigned32, + ntpProxyPeersConfigured TruthValue, + ntpProxyPeersPeerAddress IpAddress, + ntpProxyPeersPeerPort Unsigned32, + ntpProxyPeersHostAddress IpAddress, + ntpProxyPeersHostPort Unsigned32, + ntpProxyPeersLeap NTPLeapIndicator, + ntpProxyPeersMode INTEGER, + ntpProxyPeersStratum Integer32, + ntpProxyPeersPeerPoll Integer32, + ntpProxyPeersHostPoll Integer32, + ntpProxyPeersPrecision Integer32, + ntpProxyPeersRootDelay OCTET STRING, + ntpProxyPeersRootDispersion OCTET STRING, + ntpProxyPeersRefId OCTET STRING, + ntpProxyPeersRefTime NTPTimeStamp, + ntpProxyPeersOrgTime NTPTimeStamp, + ntpProxyPeersReceiveTime NTPTimeStamp, + ntpProxyPeersTransmitTime NTPTimeStamp, + ntpProxyPeersUpdateTime NTPTimeStamp, + ntpProxyPeersReach Unsigned32, + ntpProxyPeersTimer Integer32, + ntpProxyPeersOffset OCTET STRING, + ntpProxyPeersDelay OCTET STRING, + ntpProxyPeersDispersion OCTET STRING, + ntpProxyPeersFilterValidEntries Integer32 +} + +ntpProxyPeersAssocId OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 1 } + +ntpProxyPeersConfigured OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 2 } + +ntpProxyPeersPeerAddress OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 3 } + +ntpProxyPeersPeerPort OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 4 } + +ntpProxyPeersHostAddress OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 5 } + +ntpProxyPeersHostPort OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 6 } + +ntpProxyPeersLeap OBJECT-TYPE + SYNTAX NTPLeapIndicator + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 7 } + +ntpProxyPeersMode OBJECT-TYPE + SYNTAX INTEGER { + unspecified(0), + symmetricActive(1), + symmetricPassive(2), + client(3), + server(4), + broadcast(5), + reservedControl(6), + reservedPrivate(7) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 8 } + +ntpProxyPeersStratum OBJECT-TYPE + SYNTAX Integer32 (0..255) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 9 } + +ntpProxyPeersPeerPoll OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 10 } + +ntpProxyPeersHostPoll OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 11 } + +ntpProxyPeersPrecision OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 12 } + +ntpProxyPeersRootDelay OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 13 } + +ntpProxyPeersRootDispersion OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 14 } + +ntpProxyPeersRefId OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 15 } + +ntpProxyPeersRefTime OBJECT-TYPE + SYNTAX NTPTimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 16 } + +ntpProxyPeersOrgTime OBJECT-TYPE + SYNTAX NTPTimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 17 } + +ntpProxyPeersReceiveTime OBJECT-TYPE + SYNTAX NTPTimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 18 } + +ntpProxyPeersTransmitTime OBJECT-TYPE + SYNTAX NTPTimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 19 } + +ntpProxyPeersUpdateTime OBJECT-TYPE + SYNTAX NTPTimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 20 } + +ntpProxyPeersReach OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 21 } + +ntpProxyPeersTimer OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 22 } + +ntpProxyPeersOffset OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 23 } + +ntpProxyPeersDelay OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 24 } + +ntpProxyPeersDispersion OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyPeersVarEntry 25 } + +ntpProxyPeersFilterValidEntries OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of valid entries for a peer in the Proxy Filter + Register Table. This number can be zero." + ::= { ntpProxyPeersVarEntry 26 } + +-- +-- Proxy Filter Register Table +-- + +ntpProxyFilterRegisterTable OBJECT-TYPE + SYNTAX SEQUENCE OF NtpProxyFilterRegisterEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + ::= { ntpProxyControl 4 } + +ntpProxyFilterRegisterEntry OBJECT-TYPE + SYNTAX NtpProxyFilterRegisterEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + INDEX { ntpProxyServerIPAddr, ntpProxyPeersAssocId, + ntpProxyFilterIndex } + ::= { ntpProxyFilterRegisterTable 1 } + +NtpProxyFilterRegisterEntry ::= SEQUENCE { + ntpProxyFilterIndex Unsigned32, + ntpProxyFilterPeersOffset OCTET STRING, + ntpProxyFilterPeersDelay OCTET STRING, + ntpProxyFilterPeersDispersion OCTET STRING +} + +ntpProxyFilterIndex OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + ::= { ntpProxyFilterRegisterEntry 1 } + +ntpProxyFilterPeersOffset OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyFilterRegisterEntry 2 } + +ntpProxyFilterPeersDelay OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyFilterRegisterEntry 3 } + +ntpProxyFilterPeersDispersion OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { ntpProxyFilterRegisterEntry 4 } + +END Property changes on: vendor/bsnmp/1.13/snmp_ntp/NTP-PROXY-MIB.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_ntp/ntp_tree.def =================================================================== --- vendor/bsnmp/1.13/snmp_ntp/ntp_tree.def (nonexistent) +++ vendor/bsnmp/1.13/snmp_ntp/ntp_tree.def (revision 336778) @@ -0,0 +1,122 @@ +# +# Copyright (c) 2005 +# Hartmut Brandt. +# All rights reserved. +# +# Author: Harti Brandt +# +# Redistribution of this software and documentation and use in source and +# binary forms, with or without modification, are permitted provided that +# the following conditions are met: +# +# 1. Redistributions of source code or documentation must retain the above +# copyright notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS +# AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +# FRAUNHOFER FOKUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# $Begemot: bsnmp/snmp_ntp/ntp_tree.def,v 1.2 2005/04/26 13:38:01 brandt_h Exp $ +# +# Definition of the tree implemented by snmp_ntp. +# +(1 internet + (4 private + (1 enterprises + (1277 udel + (3 ntpMIB + (1 ntpSystem + (1 ntpSysLeap INTEGER op_ntpSystem GET) + (2 ntpSysStratum INTEGER op_ntpSystem GET) + (3 ntpSysPrecision INTEGER32 op_ntpSystem GET) + (4 ntpSysRootDelay OCTETSTRING op_ntpSystem GET) + (5 ntpSysRootDispersion OCTETSTRING op_ntpSystem GET) + (6 ntpSysRefId OCTETSTRING op_ntpSystem GET) + (7 ntpSysRefTime OCTETSTRING op_ntpSystem GET) + (8 ntpSysPoll INTEGER32 op_ntpSystem GET) + (9 ntpSysPeer UNSIGNED32 op_ntpSystem GET) +# No idea what these should be +# (10 ntpSysPhase OCTETSTRING op_ntpSystem GET) +# (11 ntpSysFreq OCTETSTRING op_ntpSystem GET) +# (12 ntpSysError OCTETSTRING op_ntpSystem GET) + (13 ntpSysClock OCTETSTRING op_ntpSystem GET) + (14 ntpSysSystem OCTETSTRING op_ntpSystem GET) + (15 ntpSysProcessor OCTETSTRING op_ntpSystem GET) + ) + (2 ntpPeers + (1 ntpPeersVarTable + (1 ntpPeersVarEntry : UNSIGNED32 op_ntpPeersVarTable + (1 ntpPeersAssocId UNSIGNED32) + (2 ntpPeersConfigured INTEGER GET) + (3 ntpPeersPeerAddress IPADDRESS GET) + (4 ntpPeersPeerPort UNSIGNED32 GET) + (5 ntpPeersHostAddress IPADDRESS GET) + (6 ntpPeersHostPort UNSIGNED32 GET) + (7 ntpPeersLeap INTEGER GET) + (8 ntpPeersMode INTEGER GET) + (9 ntpPeersStratum INTEGER GET) + (10 ntpPeersPeerPoll INTEGER32 GET) + (11 ntpPeersHostPoll INTEGER32 GET) + (12 ntpPeersPrecision INTEGER32 GET) + (13 ntpPeersRootDelay OCTETSTRING GET) + (14 ntpPeersRootDispersion OCTETSTRING GET) + (15 ntpPeersRefId OCTETSTRING GET) + (16 ntpPeersRefTime OCTETSTRING GET) + (17 ntpPeersOrgTime OCTETSTRING GET) + (18 ntpPeersReceiveTime OCTETSTRING GET) + (19 ntpPeersTransmitTime OCTETSTRING GET) +# No idea what these should be +# (20 ntpPeersUpdateTime OCTETSTRING GET) + (21 ntpPeersReach UNSIGNED32 GET) + (22 ntpPeersTimer INTEGER32 GET) + (23 ntpPeersOffset OCTETSTRING GET) + (24 ntpPeersDelay OCTETSTRING GET) + (25 ntpPeersDispersion OCTETSTRING GET) + ) + ) + ) + (3 ntpFilter + (1 ntpFilterPeersVarTable + (1 ntpFilterPeersVarEntry : UNSIGNED32 op_ntpFilterPeersVarTable + (1 ntpFilterValidEntries INTEGER32 GET) + ) + ) + (2 ntpFilterRegisterTable + (1 ntpFilterRegisterEntry : UNSIGNED32 UNSIGNED32 op_ntpFilterRegisterTable + (1 ntpFilterIndex UNSIGNED32) + (2 ntpFilterPeersOffset OCTETSTRING GET) + (3 ntpFilterPeersDelay OCTETSTRING GET) + (4 ntpFilterPeersDispersion OCTETSTRING GET) + ) + ) + ) + ) + ) + (12325 fokus + (1 begemot + (201 begemotNtp + (1 begemotNtpObjects + (1 begemotNtpHost OCTETSTRING op_begemot_ntp GET) + (2 begemotNtpPort OCTETSTRING op_begemot_ntp GET) + (3 begemotNtpTimeout TIMETICKS op_begemot_ntp GET SET) + (4 begemotNtpDebug UNSIGNED32 op_begemot_ntp GET SET) + (5 begemotNtpJitter COUNTER64 op_begemot_ntp GET) + (6 begemotNtpStability COUNTER64 op_begemot_ntp GET) + ) + ) + ) + ) + ) + ) +) Property changes on: vendor/bsnmp/1.13/snmp_ntp/ntp_tree.def ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_ntp/snmp_ntp.c =================================================================== --- vendor/bsnmp/1.13/snmp_ntp/snmp_ntp.c (nonexistent) +++ vendor/bsnmp/1.13/snmp_ntp/snmp_ntp.c (revision 336778) @@ -0,0 +1,1598 @@ +/* + * Copyright (c) 2005 + * Hartmut Brandt. + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution of this software and documentation and use in source and + * binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * + * 1. Redistributions of source code or documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS + * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * FRAUNHOFER FOKUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Begemot: bsnmp/snmp_ntp/snmp_ntp.c,v 1.9 2005/10/06 07:15:01 brandt_h Exp $ + * + * NTP interface for SNMPd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_STDINT_H +#include +#elif defined(HAVE_INTTYPES_H) +#include +#endif +#include +#include +#include +#include +#include + +#include "support.h" +#include "snmpmod.h" +#include "ntp_tree.h" +#include "ntp_oid.h" + +#define NTPC_MAX 576 +#define NTPC_VERSION 3 +#define NTPC_MODE 6 +#define NTPC_DMAX 468 + +#define NTPC_BIT_RESP 0x80 +#define NTPC_BIT_ERROR 0x40 +#define NTPC_BIT_MORE 0x20 + +#define NTPC_OPMASK 0x1f +#define NTPC_OP_READSTAT 1 +#define NTPC_OP_READVAR 2 + +/* our module handle */ +static struct lmodule *module; + +/* debug flag */ +static uint32_t ntp_debug; +#define DBG_DUMP_PKTS 0x01 +#define DBG_DUMP_VARS 0x02 + +/* OIDs */ +static const struct asn_oid oid_ntpMIB = OIDX_ntpMIB; + +/* the Object Resource registration index */ +static u_int reg_index; + +/* last time we've fetch the system variables */ +static uint64_t sysinfo_tick; + +/* cached system variables */ +static int32_t sys_leap; +static int sysb_leap; +static int32_t sys_stratum; +static int sysb_stratum; +static int32_t sys_precision; +static int sysb_precision; +static char *sys_rootdelay; +static char *sys_rootdispersion; +static char *sys_refid; +static char sys_reftime[8]; +static int sysb_reftime; +static int32_t sys_poll; +static int sysb_poll; +static uint32_t sys_peer; +static int sysb_peer; +static u_char sys_clock[8]; +static int sysb_clock; +static char *sys_system; +static char *sys_processor; +static int sysb_jitter; +static double sys_jitter; +static int sysb_stability; +static double sys_stability; + +/* last time we've fetch the peer list */ +static uint64_t peers_tick; + +/* request sequence number generator */ +static uint16_t seqno; + +/* NTPD socket */ +static int ntpd_sock; +static void *ntpd_fd; + +struct peer { + /* required entries for macros */ + uint32_t index; + TAILQ_ENTRY(peer) link; + + int32_t config; /* config bit */ + u_char srcadr[4]; /* PeerAddress */ + uint32_t srcport; /* PeerPort */ + u_char dstadr[4]; /* HostAddress */ + uint32_t dstport; /* HostPort */ + int32_t leap; /* Leap */ + int32_t hmode; /* Mode */ + int32_t stratum; /* Stratum */ + int32_t ppoll; /* PeerPoll */ + int32_t hpoll; /* HostPoll */ + int32_t precision; /* Precision */ + char *rootdelay; /* RootDelay */ + char *rootdispersion;/* RootDispersion */ + char *refid; /* RefId */ + u_char reftime[8]; /* RefTime */ + u_char orgtime[8]; /* OrgTime */ + u_char rcvtime[8]; /* ReceiveTime */ + u_char xmttime[8]; /* TransmitTime */ + u_int32_t reach; /* Reach */ + int32_t timer; /* Timer */ + char *offset; /* Offset */ + char *delay; /* Delay */ + char *dispersion; /* Dispersion */ + int32_t filt_entries; +}; +TAILQ_HEAD(peer_list, peer); + +/* list of peers */ +static struct peer_list peers = TAILQ_HEAD_INITIALIZER(peers); + +struct filt { + /* required fields */ + struct asn_oid index; + TAILQ_ENTRY(filt) link; + + char *offset; + char *delay; + char *dispersion; +}; +TAILQ_HEAD(filt_list, filt); + +/* list of filters */ +static struct filt_list filts = TAILQ_HEAD_INITIALIZER(filts); + +/* configuration */ +static u_char *ntp_host; +static u_char *ntp_port; +static uint32_t ntp_timeout; + +static void ntpd_input(int, void *); +static int open_socket(void); + +/* the initialization function */ +static int +ntp_init(struct lmodule *mod, int argc, char *argv[] __unused) +{ + + module = mod; + + if (argc != 0) { + syslog(LOG_ERR, "bad number of arguments for %s", __func__); + return (EINVAL); + } + + ntp_host = strdup("localhost"); + ntp_port = strdup("ntp"); + ntp_timeout = 50; /* 0.5sec */ + + return (0); +} + +/* + * Module is started + */ +static void +ntp_start(void) +{ + + if (open_socket() != -1) { + ntpd_fd = fd_select(ntpd_sock, ntpd_input, NULL, module); + if (ntpd_fd == NULL) { + syslog(LOG_ERR, "fd_select failed on ntpd socket: %m"); + return; + } + } + reg_index = or_register(&oid_ntpMIB, "The MIB for NTP.", module); +} + +/* + * Called, when the module is to be unloaded after it was successfully loaded + */ +static int +ntp_fini(void) +{ + + or_unregister(reg_index); + fd_deselect(ntpd_fd); + + return (0); +} + +const struct snmp_module config = { + .comment = "This module implements the NTP MIB", + .init = ntp_init, + .start = ntp_start, + .fini = ntp_fini, + .tree = ntp_ctree, + .tree_size = ntp_CTREE_SIZE, +}; + +/* + * Open the NTPD socket + */ +static int +open_socket(void) +{ + struct addrinfo hints, *res, *res0; + int error; + const char *cause; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + + error = getaddrinfo(ntp_host, ntp_port, &hints, &res0); + if (error) { + syslog(LOG_ERR, "%s(%s): %s", ntp_host, ntp_port, + gai_strerror(error)); + return (-1); + } + + ntpd_sock = -1; + cause = "no address"; + errno = EADDRNOTAVAIL; + for (res = res0; res != NULL; res = res->ai_next) { + ntpd_sock = socket(res->ai_family, res->ai_socktype, + res->ai_protocol); + if (ntpd_sock == -1) { + cause = "socket"; + continue; + } + if (connect(ntpd_sock, res->ai_addr, res->ai_addrlen) == -1) { + cause = "connect"; + (void)close(ntpd_sock); + ntpd_sock = -1; + continue; + } + break; + } + if (ntpd_sock == -1) { + syslog(LOG_ERR, "%s: %m", cause); + return (-1); + } + freeaddrinfo(res0); + return (0); +} + +/* + * Dump a packet + */ +static void +dump_packet(const u_char *pkt, size_t ret) +{ + char buf[8 * 3 + 1]; + size_t i, j; + + for (i = 0; i < ret; i += 8) { + buf[0] = '\0'; + for (j = 0; i + j < (size_t)ret && j < 8; j++) + sprintf(buf + strlen(buf), " %02x", pkt[i + j]); + syslog(LOG_INFO, "%04zu:%s", i, buf); + } +} + +/* + * Execute an NTP request. + */ +static int +ntpd_request(u_int op, u_int associd, const char *vars) +{ + u_char *rpkt; + u_char *ptr; + size_t vlen; + ssize_t ret; + + if ((rpkt = malloc(NTPC_MAX)) == NULL) { + syslog(LOG_ERR, "%m"); + return (-1); + } + memset(rpkt, 0, NTPC_MAX); + + ptr = rpkt; + *ptr++ = (NTPC_VERSION << 3) | NTPC_MODE; + *ptr++ = op; + + if (++seqno == 0) + seqno++; + *ptr++ = seqno >> 8; + *ptr++ = seqno; + + /* skip status */ + ptr += 2; + + *ptr++ = associd >> 8; + *ptr++ = associd; + + /* skip offset */ + ptr += 2; + + if (vars != NULL) { + vlen = strlen(vars); + if (vlen > NTPC_DMAX) { + syslog(LOG_ERR, "NTP request too long (%zu)", vlen); + free(rpkt); + return (-1); + } + *ptr++ = vlen >> 8; + *ptr++ = vlen; + + memcpy(ptr, vars, vlen); + ptr += vlen; + } else + /* skip data length (is already zero) */ + ptr += 2; + + while ((ptr - rpkt) % 4 != 0) + *ptr++ = 0; + + if (ntp_debug & DBG_DUMP_PKTS) { + syslog(LOG_INFO, "sending %zd bytes", ptr - rpkt); + dump_packet(rpkt, ptr - rpkt); + } + + ret = send(ntpd_sock, rpkt, ptr - rpkt, 0); + if (ret == -1) { + syslog(LOG_ERR, "cannot send to ntpd: %m"); + free(rpkt); + return (-1); + } + return (0); +} + +/* + * Callback if packet arrived from NTPD + */ +static int +ntpd_read(uint16_t *op, uint16_t *associd, u_char **data, size_t *datalen) +{ + u_char pkt[NTPC_MAX + 1]; + u_char *ptr, *nptr; + u_int n; + ssize_t ret; + size_t z; + u_int offset; /* current offset */ + int more; /* more flag */ + int sel; + struct timeval inc, end, rem; + fd_set iset; + + *datalen = 0; + *data = NULL; + offset = 0; + + inc.tv_sec = ntp_timeout / 100; + inc.tv_usec = (ntp_timeout % 100) * 1000; + + (void)gettimeofday(&end, NULL); + timeradd(&end, &inc, &end); + + next: + /* compute remaining time */ + (void)gettimeofday(&rem, NULL); + if (timercmp(&rem, &end, >=)) { + /* do a poll */ + rem.tv_sec = 0; + rem.tv_usec = 0; + } else { + timersub(&end, &rem, &rem); + } + + /* select */ + FD_ZERO(&iset); + FD_SET(ntpd_sock, &iset); + sel = select(ntpd_sock + 1, &iset, NULL, NULL, &rem); + if (sel == -1) { + if (errno == EINTR) + goto next; + syslog(LOG_ERR, "select ntpd_sock: %m"); + free(*data); + return (-1); + } + if (sel == 0) { + syslog(LOG_ERR, "timeout on NTP connection"); + free(*data); + return (-1); + } + + /* now read it */ + ret = recv(ntpd_sock, pkt, sizeof(pkt), 0); + if (ret == -1) { + syslog(LOG_ERR, "error reading from ntpd: %m"); + free(*data); + return (-1); + } + + if (ntp_debug & DBG_DUMP_PKTS) { + syslog(LOG_INFO, "got %zd bytes", ret); + dump_packet(pkt, (size_t)ret); + } + + ptr = pkt; + if ((*ptr & 0x3f) != ((NTPC_VERSION << 3) | NTPC_MODE)) { + syslog(LOG_ERR, "unexpected packet version 0x%x", *ptr); + free(*data); + return (-1); + } + ptr++; + + if (!(*ptr & NTPC_BIT_RESP)) { + syslog(LOG_ERR, "not a response packet"); + return (-1); + } + if (*ptr & NTPC_BIT_ERROR) { + z = *datalen - 12; + if (z > NTPC_DMAX) + z = NTPC_DMAX; + syslog(LOG_ERR, "error response: %.*s", (int)z, pkt + 12); + free(*data); + return (-1); + } + more = (*ptr & NTPC_BIT_MORE); + + *op = *ptr++ & NTPC_OPMASK; + + /* seqno */ + n = *ptr++ << 8; + n |= *ptr++; + + if (n != seqno) { + syslog(LOG_ERR, "expecting seqno %u, got %u", seqno, n); + free(*data); + return (-1); + } + + /* status */ + n = *ptr++ << 8; + n |= *ptr++; + + /* associd */ + *associd = *ptr++ << 8; + *associd |= *ptr++; + + /* offset */ + n = *ptr++ << 8; + n |= *ptr++; + + if (n != offset) { + syslog(LOG_ERR, "offset: expecting %u, got %u", offset, n); + free(*data); + return (-1); + } + + /* count */ + n = *ptr++ << 8; + n |= *ptr++; + + if ((size_t)ret < 12 + n) { + syslog(LOG_ERR, "packet too short"); + return (-1); + } + + nptr = realloc(*data, *datalen + n); + if (nptr == NULL) { + syslog(LOG_ERR, "cannot allocate memory: %m"); + free(*data); + return (-1); + } + *data = nptr; + + memcpy(*data + offset, ptr, n); + *datalen += n; + + if (!more) + return (0); + + offset += n; + goto next; +} + +/* + * Send a request and wait for the response + */ +static int +ntpd_dialog(u_int op, u_int associd, const char *vars, u_char **data, + size_t *datalen) +{ + uint16_t rassocid; + uint16_t rop; + + if (ntpd_request(op, associd, vars) == -1) + return (-1); + if (ntpd_read(&rop, &rassocid, data, datalen) == -1) + return (-1); + + if (rop != op) { + syslog(LOG_ERR, "bad response op 0x%x", rop); + free(data); + return (-1); + } + + if (associd != rassocid) { + syslog(LOG_ERR, "response for wrong associd"); + free(data); + return (-1); + } + return (0); +} + +/* + * Callback if packet arrived from NTPD + */ +static void +ntpd_input(int fd __unused, void *arg __unused) +{ + uint16_t associd; + uint16_t op; + u_char *data; + size_t datalen; + + if (ntpd_read(&op, &associd, &data, &datalen) == -1) + return; + + free(data); +} + +/* + * Find the value of a variable + */ +static int +ntpd_parse(u_char **data, size_t *datalen, char **namep, char **valp) +{ + u_char *ptr = *data; + u_char *end = ptr + *datalen; + char *ptr1; + char endc; + + /* skip leading spaces */ + while (ptr < end && isspace((int)*ptr)) + ptr++; + + if (ptr == end) + return (0); + + *namep = ptr; + + /* skip to space or '=' or ','*/ + while (ptr < end && !isspace((int)*ptr) && *ptr != '=' && *ptr != ',') + ptr++; + endc = *ptr; + *ptr++ = '\0'; + + /* skip space */ + while (ptr < end && isspace((int)*ptr)) + ptr++; + + if (ptr == end || endc == ',') { + /* no value */ + *valp = NULL; + *datalen -= ptr - *data; + *data = ptr; + return (1); + } + + if (*ptr == '"') { + /* quoted */ + ptr++; + *valp = ptr; + while (ptr < end && *ptr != '"') + ptr++; + if (ptr == end) + return (0); + + *ptr++ = '\0'; + + /* find comma */ + while (ptr < end && isspace((int)*ptr) && *ptr == ',') + ptr++; + } else { + *valp = ptr; + + /* skip to end of value */ + while (ptr < end && *ptr != ',') + ptr++; + + /* remove trailing blanks */ + for (ptr1 = ptr; ptr1 > *valp; ptr1--) + if (!isspace((int)ptr1[-1])) + break; + *ptr1 = '\0'; + + if (ptr < end) + ptr++; + } + + *datalen -= ptr - *data; + *data = ptr; + + return (1); +} + +/* + * Parse an int32 value + */ +static int +val_parse_int32(const char *val, int32_t *p, int32_t min, int32_t max, int base) +{ + long n; + char *end; + + errno = 0; + n = strtol(val, &end, base); + if (errno != 0 || *end != '\0') + return (0); + if (n < min || n > max) + return (0); + *p = (int32_t)n; + return (1); +} + +/* + * Parse an uint32 value + */ +static int +val_parse_uint32(const char *val, uint32_t *p, uint32_t min, uint32_t max, + int base) +{ + u_long n; + char *end; + + errno = 0; + n = strtoul(val, &end, base); + if (errno != 0 || *end != '\0') + return (0); + if (n < min || n > max) + return (0); + *p = (uint32_t)n; + return (1); +} + +/* + * Parse a double + */ +static int +val_parse_double(const char *val, double *p) +{ + char *end; + + errno = 0; + *p = strtod(val, &end); + if (errno != 0 || *end != '\0') + return (0); + return (1); +} + +static int +val_parse_ts(const char *val, char *buf) +{ + int r, n; + u_int i, f; + + if (strlen(val) > 2 && val[0] == '0' && val[1] == 'x') { + /* hex format */ + r = sscanf(val + 2, "%x.%x%n", &i, &f, &n); + if (r != 2 || (size_t)n != strlen(val + 2)) + return (0); + } else { + /* probably decimal */ + r = sscanf(val, "%d.%d%n", &i, &f, &n); + if (r != 2 || (size_t)n != strlen(val)) + return (0); + } + buf[0] = i >> 24; + buf[1] = i >> 16; + buf[2] = i >> 8; + buf[3] = i >> 0; + buf[4] = f >> 24; + buf[5] = f >> 16; + buf[6] = f >> 8; + buf[7] = f >> 0; + return (1); +} + +/* + * Parse an IP address. This resolves non-numeric names. + */ +static int +val_parse_ip(const char *val, u_char ip[4]) +{ + int r, n, error; + struct addrinfo hints, *res0; + struct sockaddr_in *sin_local; + + r = sscanf(val, "%hhd.%hhd.%hhd.%hhd%n", + &ip[0], &ip[1], &ip[2], &ip[3], &n); + if (n == 4 && (size_t)n == strlen(val)) + return (0); + + memset(ip, 0, 4); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + + error = getaddrinfo(val, NULL, &hints, &res0); + if (error) { + syslog(LOG_ERR, "%s: %s", val, gai_strerror(error)); + return (-1); + } + if (res0 == NULL) { + syslog(LOG_ERR, "%s: no address", val); + return (-1); + } + + sin_local = (struct sockaddr_in *)(void *)res0->ai_addr; + ip[3] = sin_local->sin_addr.s_addr >> 24; + ip[2] = sin_local->sin_addr.s_addr >> 16; + ip[1] = sin_local->sin_addr.s_addr >> 8; + ip[0] = sin_local->sin_addr.s_addr >> 0; + + freeaddrinfo(res0); + return (0); +} + +/* + * Fetch system info + */ +static int +fetch_sysinfo(void) +{ + u_char *data; + u_char *ptr; + size_t datalen; + char *name; + char *val; + + if (ntpd_dialog(NTPC_OP_READVAR, 0, + "leap,stratum,precision,rootdelay,rootdispersion,refid,reftime," + "poll,peer,clock,system,processor,jitter,stability", + &data, &datalen)) + return (-1); + + /* clear info */ + sysb_leap = 0; + sysb_stratum = 0; + sysb_precision = 0; + free(sys_rootdelay); + sys_rootdelay = NULL; + free(sys_rootdispersion); + sys_rootdispersion = NULL; + free(sys_refid); + sys_refid = NULL; + sysb_reftime = 0; + sysb_poll = 0; + sysb_peer = 0; + sysb_clock = 0; + free(sys_system); + sys_system = NULL; + free(sys_processor); + sys_processor = NULL; + sysb_jitter = 0; + sysb_stability = 0; + + ptr = data; + while (ntpd_parse(&ptr, &datalen, &name, &val)) { + if (ntp_debug & DBG_DUMP_VARS) + syslog(LOG_DEBUG, "%s: '%s'='%s'", __func__, name, val); + if (strcmp(name, "leap") == 0 || + strcmp(name, "sys.leap") == 0) { + sysb_leap = val_parse_int32(val, &sys_leap, + 0, 3, 2); + + } else if (strcmp(name, "stratum") == 0 || + strcmp(name, "sys.stratum") == 0) { + sysb_stratum = val_parse_int32(val, &sys_stratum, + 0, 255, 0); + + } else if (strcmp(name, "precision") == 0 || + strcmp(name, "sys.precision") == 0) { + sysb_precision = val_parse_int32(val, &sys_precision, + INT32_MIN, INT32_MAX, 0); + + } else if (strcmp(name, "rootdelay") == 0 || + strcmp(name, "sys.rootdelay") == 0) { + sys_rootdelay = strdup(val); + + } else if (strcmp(name, "rootdispersion") == 0 || + strcmp(name, "sys.rootdispersion") == 0) { + sys_rootdispersion = strdup(val); + + } else if (strcmp(name, "refid") == 0 || + strcmp(name, "sys.refid") == 0) { + sys_refid = strdup(val); + + } else if (strcmp(name, "reftime") == 0 || + strcmp(name, "sys.reftime") == 0) { + sysb_reftime = val_parse_ts(val, sys_reftime); + + } else if (strcmp(name, "poll") == 0 || + strcmp(name, "sys.poll") == 0) { + sysb_poll = val_parse_int32(val, &sys_poll, + INT32_MIN, INT32_MAX, 0); + + } else if (strcmp(name, "peer") == 0 || + strcmp(name, "sys.peer") == 0) { + sysb_peer = val_parse_uint32(val, &sys_peer, + 0, UINT32_MAX, 0); + + } else if (strcmp(name, "clock") == 0 || + strcmp(name, "sys.clock") == 0) { + sysb_clock = val_parse_ts(val, sys_clock); + + } else if (strcmp(name, "system") == 0 || + strcmp(name, "sys.system") == 0) { + sys_system = strdup(val); + + } else if (strcmp(name, "processor") == 0 || + strcmp(name, "sys.processor") == 0) { + sys_processor = strdup(val); + + } else if (strcmp(name, "jitter") == 0 || + strcmp(name, "sys.jitter") == 0) { + sysb_jitter = val_parse_double(val, &sys_jitter); + + } else if (strcmp(name, "stability") == 0 || + strcmp(name, "sys.stability") == 0) { + sysb_stability = val_parse_double(val, &sys_stability); + } + } + + free(data); + return (0); +} + +static int +parse_filt(char *val, uint16_t associd, int which) +{ + char *w; + int cnt; + struct filt *f; + + cnt = 0; + for (w = strtok(val, " \t"); w != NULL; w = strtok(NULL, " \t")) { + TAILQ_FOREACH(f, &filts, link) + if (f->index.subs[0] == associd && + f->index.subs[1] == (asn_subid_t)(cnt + 1)) + break; + if (f == NULL) { + f = malloc(sizeof(*f)); + memset(f, 0, sizeof(*f)); + f->index.len = 2; + f->index.subs[0] = associd; + f->index.subs[1] = cnt + 1; + + INSERT_OBJECT_OID(f, &filts); + } + + switch (which) { + + case 0: + f->offset = strdup(w); + break; + + case 1: + f->delay = strdup(w); + break; + + case 2: + f->dispersion = strdup(w); + break; + + default: + abort(); + } + cnt++; + } + return (cnt); +} + +/* + * Fetch the complete peer list + */ +static int +fetch_peers(void) +{ + u_char *data, *pdata, *ptr; + size_t datalen, pdatalen; + int i; + struct peer *p; + struct filt *f; + uint16_t associd; + char *name, *val; + + /* free the old list */ + while ((p = TAILQ_FIRST(&peers)) != NULL) { + TAILQ_REMOVE(&peers, p, link); + free(p->rootdelay); + free(p->rootdispersion); + free(p->refid); + free(p->offset); + free(p->delay); + free(p->dispersion); + free(p); + } + while ((f = TAILQ_FIRST(&filts)) != NULL) { + TAILQ_REMOVE(&filts, f, link); + free(f->offset); + free(f->delay); + free(f->dispersion); + free(f); + } + + /* fetch the list of associations */ + if (ntpd_dialog(NTPC_OP_READSTAT, 0, NULL, &data, &datalen)) + return (-1); + + for (i = 0; i < (int)(datalen / 4); i++) { + associd = data[4 * i + 0] << 8; + associd |= data[4 * i + 1] << 0; + + /* ask for the association variables */ + if (ntpd_dialog(NTPC_OP_READVAR, associd, + "config,srcadr,srcport,dstadr,dstport,leap,hmode,stratum," + "hpoll,ppoll,precision,rootdelay,rootdispersion,refid," + "reftime,org,rec,xmt,reach,timer,offset,delay,dispersion," + "filtdelay,filtoffset,filtdisp", + &pdata, &pdatalen)) { + free(data); + return (-1); + } + + /* now save and parse the data */ + p = malloc(sizeof(*p)); + if (p == NULL) { + free(data); + syslog(LOG_ERR, "%m"); + return (-1); + } + memset(p, 0, sizeof(*p)); + p->index = associd; + INSERT_OBJECT_INT(p, &peers); + + ptr = pdata; + while (ntpd_parse(&ptr, &pdatalen, &name, &val)) { + if (ntp_debug & DBG_DUMP_VARS) + syslog(LOG_DEBUG, "%s: '%s'='%s'", + __func__, name, val); + if (strcmp(name, "config") == 0 || + strcmp(name, "peer.config") == 0) { + val_parse_int32(val, &p->config, 0, 1, 0); + + } else if (strcmp(name, "srcadr") == 0 || + strcmp(name, "peer.srcadr") == 0) { + val_parse_ip(val, p->srcadr); + + } else if (strcmp(name, "srcport") == 0 || + strcmp(name, "peer.srcport") == 0) { + val_parse_uint32(val, &p->srcport, + 1, 65535, 0); + + } else if (strcmp(name, "dstadr") == 0 || + strcmp(name, "peer.dstadr") == 0) { + val_parse_ip(val, p->dstadr); + + } else if (strcmp(name, "dstport") == 0 || + strcmp(name, "peer.dstport") == 0) { + val_parse_uint32(val, &p->dstport, + 1, 65535, 0); + + } else if (strcmp(name, "leap") == 0 || + strcmp(name, "peer.leap") == 0) { + val_parse_int32(val, &p->leap, 0, 3, 2); + + } else if (strcmp(name, "hmode") == 0 || + strcmp(name, "peer.hmode") == 0) { + val_parse_int32(val, &p->hmode, 0, 7, 0); + + } else if (strcmp(name, "stratum") == 0 || + strcmp(name, "peer.stratum") == 0) { + val_parse_int32(val, &p->stratum, 0, 255, 0); + + } else if (strcmp(name, "ppoll") == 0 || + strcmp(name, "peer.ppoll") == 0) { + val_parse_int32(val, &p->ppoll, + INT32_MIN, INT32_MAX, 0); + + } else if (strcmp(name, "hpoll") == 0 || + strcmp(name, "peer.hpoll") == 0) { + val_parse_int32(val, &p->hpoll, + INT32_MIN, INT32_MAX, 0); + + } else if (strcmp(name, "precision") == 0 || + strcmp(name, "peer.precision") == 0) { + val_parse_int32(val, &p->hpoll, + INT32_MIN, INT32_MAX, 0); + + } else if (strcmp(name, "rootdelay") == 0 || + strcmp(name, "peer.rootdelay") == 0) { + p->rootdelay = strdup(val); + + } else if (strcmp(name, "rootdispersion") == 0 || + strcmp(name, "peer.rootdispersion") == 0) { + p->rootdispersion = strdup(val); + + } else if (strcmp(name, "refid") == 0 || + strcmp(name, "peer.refid") == 0) { + p->refid = strdup(val); + + } else if (strcmp(name, "reftime") == 0 || + strcmp(name, "sys.reftime") == 0) { + val_parse_ts(val, p->reftime); + + } else if (strcmp(name, "org") == 0 || + strcmp(name, "sys.org") == 0) { + val_parse_ts(val, p->orgtime); + + } else if (strcmp(name, "rec") == 0 || + strcmp(name, "sys.rec") == 0) { + val_parse_ts(val, p->rcvtime); + + } else if (strcmp(name, "xmt") == 0 || + strcmp(name, "sys.xmt") == 0) { + val_parse_ts(val, p->xmttime); + + } else if (strcmp(name, "reach") == 0 || + strcmp(name, "peer.reach") == 0) { + val_parse_uint32(val, &p->reach, + 0, 65535, 0); + + } else if (strcmp(name, "timer") == 0 || + strcmp(name, "peer.timer") == 0) { + val_parse_int32(val, &p->timer, + INT32_MIN, INT32_MAX, 0); + + } else if (strcmp(name, "offset") == 0 || + strcmp(name, "peer.offset") == 0) { + p->offset = strdup(val); + + } else if (strcmp(name, "delay") == 0 || + strcmp(name, "peer.delay") == 0) { + p->delay = strdup(val); + + } else if (strcmp(name, "dispersion") == 0 || + strcmp(name, "peer.dispersion") == 0) { + p->dispersion = strdup(val); + + } else if (strcmp(name, "filtdelay") == 0 || + strcmp(name, "peer.filtdelay") == 0) { + p->filt_entries = parse_filt(val, associd, 0); + + } else if (strcmp(name, "filtoffset") == 0 || + strcmp(name, "peer.filtoffset") == 0) { + p->filt_entries = parse_filt(val, associd, 1); + + } else if (strcmp(name, "filtdisp") == 0 || + strcmp(name, "peer.filtdisp") == 0) { + p->filt_entries = parse_filt(val, associd, 2); + } + } + free(pdata); + } + + free(data); + return (0); +} + +/* + * System variables - read-only scalars only. + */ +int +op_ntpSystem(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + if (this_tick > sysinfo_tick) { + if (fetch_sysinfo() == -1) + return (SNMP_ERR_GENERR); + sysinfo_tick = this_tick; + } + + switch (which) { + + case LEAF_ntpSysLeap: + if (!sysb_leap) + return (SNMP_ERR_NOSUCHNAME); + value->v.integer = sys_leap; + break; + + case LEAF_ntpSysStratum: + if (!sysb_stratum) + return (SNMP_ERR_NOSUCHNAME); + value->v.integer = sys_stratum; + break; + + case LEAF_ntpSysPrecision: + if (!sysb_precision) + return (SNMP_ERR_NOSUCHNAME); + value->v.integer = sys_precision; + break; + + case LEAF_ntpSysRootDelay: + if (sys_rootdelay == NULL) + return (SNMP_ERR_NOSUCHNAME); + return (string_get(value, sys_rootdelay, -1)); + + case LEAF_ntpSysRootDispersion: + if (sys_rootdispersion == NULL) + return (SNMP_ERR_NOSUCHNAME); + return (string_get(value, sys_rootdispersion, -1)); + + case LEAF_ntpSysRefId: + if (sys_refid == NULL) + return (SNMP_ERR_NOSUCHNAME); + return (string_get(value, sys_refid, -1)); + + case LEAF_ntpSysRefTime: + if (sysb_reftime == 0) + return (SNMP_ERR_NOSUCHNAME); + return (string_get(value, sys_reftime, 8)); + + case LEAF_ntpSysPoll: + if (sysb_poll == 0) + return (SNMP_ERR_NOSUCHNAME); + value->v.integer = sys_poll; + break; + + case LEAF_ntpSysPeer: + if (sysb_peer == 0) + return (SNMP_ERR_NOSUCHNAME); + value->v.uint32 = sys_peer; + break; + + case LEAF_ntpSysClock: + if (sysb_clock == 0) + return (SNMP_ERR_NOSUCHNAME); + return (string_get(value, sys_clock, 8)); + + case LEAF_ntpSysSystem: + if (sys_system == NULL) + return (SNMP_ERR_NOSUCHNAME); + return (string_get(value, sys_system, -1)); + + case LEAF_ntpSysProcessor: + if (sys_processor == NULL) + return (SNMP_ERR_NOSUCHNAME); + return (string_get(value, sys_processor, -1)); + + default: + abort(); + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_COMMIT: + case SNMP_OP_ROLLBACK: + abort(); + } + abort(); +} + +int +op_ntpPeersVarTable(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + uint32_t peer; + struct peer *t; + + if (this_tick > peers_tick) { + if (fetch_peers() == -1) + return (SNMP_ERR_GENERR); + peers_tick = this_tick; + } + + switch (op) { + + case SNMP_OP_GETNEXT: + t = NEXT_OBJECT_INT(&peers, &value->var, sub); + if (t == NULL) + return (SNMP_ERR_NOSUCHNAME); + value->var.len = sub + 1; + value->var.subs[sub] = t->index; + break; + + case SNMP_OP_GET: + t = FIND_OBJECT_INT(&peers, &value->var, sub); + if (t == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if (index_decode(&value->var, sub, iidx, &peer)) + return (SNMP_ERR_NO_CREATION); + t = FIND_OBJECT_INT(&peers, &value->var, sub); + if (t != NULL) + return (SNMP_ERR_NOT_WRITEABLE); + return (SNMP_ERR_NO_CREATION); + + case SNMP_OP_COMMIT: + case SNMP_OP_ROLLBACK: + default: + abort(); + } + + /* + * Come here for GET and COMMIT + */ + switch (which) { + + case LEAF_ntpPeersConfigured: + value->v.integer = t->config; + break; + + case LEAF_ntpPeersPeerAddress: + return (ip_get(value, t->srcadr)); + + case LEAF_ntpPeersPeerPort: + value->v.uint32 = t->srcport; + break; + + case LEAF_ntpPeersHostAddress: + return (ip_get(value, t->dstadr)); + + case LEAF_ntpPeersHostPort: + value->v.uint32 = t->dstport; + break; + + case LEAF_ntpPeersLeap: + value->v.integer = t->leap; + break; + + case LEAF_ntpPeersMode: + value->v.integer = t->hmode; + break; + + case LEAF_ntpPeersStratum: + value->v.integer = t->stratum; + break; + + case LEAF_ntpPeersPeerPoll: + value->v.integer = t->ppoll; + break; + + case LEAF_ntpPeersHostPoll: + value->v.integer = t->hpoll; + break; + + case LEAF_ntpPeersPrecision: + value->v.integer = t->precision; + break; + + case LEAF_ntpPeersRootDelay: + return (string_get(value, t->rootdelay, -1)); + + case LEAF_ntpPeersRootDispersion: + return (string_get(value, t->rootdispersion, -1)); + + case LEAF_ntpPeersRefId: + return (string_get(value, t->refid, -1)); + + case LEAF_ntpPeersRefTime: + return (string_get(value, t->reftime, 8)); + + case LEAF_ntpPeersOrgTime: + return (string_get(value, t->orgtime, 8)); + + case LEAF_ntpPeersReceiveTime: + return (string_get(value, t->rcvtime, 8)); + + case LEAF_ntpPeersTransmitTime: + return (string_get(value, t->xmttime, 8)); + + case LEAF_ntpPeersReach: + value->v.uint32 = t->reach; + break; + + case LEAF_ntpPeersTimer: + value->v.uint32 = t->timer; + break; + + case LEAF_ntpPeersOffset: + return (string_get(value, t->offset, -1)); + + case LEAF_ntpPeersDelay: + return (string_get(value, t->delay, -1)); + + case LEAF_ntpPeersDispersion: + return (string_get(value, t->dispersion, -1)); + + default: + abort(); + } + return (SNMP_ERR_NOERROR); +} + + +int +op_ntpFilterPeersVarTable(struct snmp_context *ctx __unused, + struct snmp_value *value, u_int sub, u_int iidx, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + uint32_t peer; + struct peer *t; + + if (this_tick > peers_tick) { + if (fetch_peers() == -1) + return (SNMP_ERR_GENERR); + peers_tick = this_tick; + } + + switch (op) { + + case SNMP_OP_GETNEXT: + t = NEXT_OBJECT_INT(&peers, &value->var, sub); + if (t == NULL) + return (SNMP_ERR_NOSUCHNAME); + value->var.len = sub + 1; + value->var.subs[sub] = t->index; + break; + + case SNMP_OP_GET: + t = FIND_OBJECT_INT(&peers, &value->var, sub); + if (t == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if (index_decode(&value->var, sub, iidx, &peer)) + return (SNMP_ERR_NO_CREATION); + t = FIND_OBJECT_INT(&peers, &value->var, sub); + if (t != NULL) + return (SNMP_ERR_NOT_WRITEABLE); + return (SNMP_ERR_NO_CREATION); + + case SNMP_OP_COMMIT: + case SNMP_OP_ROLLBACK: + default: + abort(); + } + + /* + * Come here for GET and COMMIT + */ + switch (which) { + + case LEAF_ntpFilterValidEntries: + value->v.integer = t->filt_entries; + break; + + default: + abort(); + } + return (SNMP_ERR_NOERROR); +} + +int +op_ntpFilterRegisterTable(struct snmp_context *ctx __unused, struct snmp_value *value __unused, + u_int sub __unused, u_int iidx __unused, enum snmp_op op __unused) +{ + asn_subid_t which = value->var.subs[sub - 1]; + uint32_t peer; + uint32_t filt; + struct filt *t; + + if (this_tick > peers_tick) { + if (fetch_peers() == -1) + return (SNMP_ERR_GENERR); + peers_tick = this_tick; + } + + switch (op) { + + case SNMP_OP_GETNEXT: + t = NEXT_OBJECT_OID(&filts, &value->var, sub); + if (t == NULL) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &t->index); + break; + + case SNMP_OP_GET: + t = FIND_OBJECT_OID(&filts, &value->var, sub); + if (t == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if (index_decode(&value->var, sub, iidx, &peer, &filt)) + return (SNMP_ERR_NO_CREATION); + t = FIND_OBJECT_OID(&filts, &value->var, sub); + if (t != NULL) + return (SNMP_ERR_NOT_WRITEABLE); + return (SNMP_ERR_NO_CREATION); + + case SNMP_OP_COMMIT: + case SNMP_OP_ROLLBACK: + default: + abort(); + } + + /* + * Come here for GET and COMMIT + */ + switch (which) { + + case LEAF_ntpFilterPeersOffset: + return (string_get(value, t->offset, -1)); + + case LEAF_ntpFilterPeersDelay: + return (string_get(value, t->delay, -1)); + + case LEAF_ntpFilterPeersDispersion: + return (string_get(value, t->dispersion, -1)); + + default: + abort(); + } + return (SNMP_ERR_NOERROR); +} + +/* + * System variables - read-only scalars only. + */ +int +op_begemot_ntp(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + int ret; + + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + switch (which) { + + case LEAF_begemotNtpHost: + return (string_get(value, ntp_host, -1)); + + case LEAF_begemotNtpPort: + return (string_get(value, ntp_port, -1)); + + case LEAF_begemotNtpTimeout: + value->v.uint32 = ntp_timeout; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNtpDebug: + value->v.uint32 = ntp_debug; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNtpJitter: + if (this_tick > sysinfo_tick) { + if (fetch_sysinfo() == -1) + return (SNMP_ERR_GENERR); + sysinfo_tick = this_tick; + } + if (!sysb_jitter) + return (SNMP_ERR_NOSUCHNAME); + value->v.counter64 = sys_jitter / 1000 * (1ULL << 32); + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNtpStability: + if (this_tick > sysinfo_tick) { + if (fetch_sysinfo() == -1) + return (SNMP_ERR_GENERR); + sysinfo_tick = this_tick; + } + if (!sysb_stability) + return (SNMP_ERR_NOSUCHNAME); + value->v.counter64 = sys_stability * (1ULL << 32); + return (SNMP_ERR_NOERROR); + } + abort(); + + case SNMP_OP_SET: + switch (which) { + + case LEAF_begemotNtpHost: + /* only at initialization */ + if (community != COMM_INITIALIZE) + return (SNMP_ERR_NOT_WRITEABLE); + + if ((ret = string_save(value, ctx, -1, &ntp_host)) + != SNMP_ERR_NOERROR) + return (ret); + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNtpPort: + /* only at initialization */ + if (community != COMM_INITIALIZE) + return (SNMP_ERR_NOT_WRITEABLE); + + if ((ret = string_save(value, ctx, -1, &ntp_port)) + != SNMP_ERR_NOERROR) + return (ret); + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNtpTimeout: + ctx->scratch->int1 = ntp_timeout; + if (value->v.uint32 < 1) + return (SNMP_ERR_WRONG_VALUE); + ntp_timeout = value->v.integer; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNtpDebug: + ctx->scratch->int1 = ntp_debug; + ntp_debug = value->v.integer; + return (SNMP_ERR_NOERROR); + } + abort(); + + case SNMP_OP_ROLLBACK: + switch (which) { + + case LEAF_begemotNtpHost: + string_rollback(ctx, &ntp_host); + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNtpPort: + string_rollback(ctx, &ntp_port); + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNtpTimeout: + ntp_timeout = ctx->scratch->int1; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNtpDebug: + ntp_debug = ctx->scratch->int1; + return (SNMP_ERR_NOERROR); + } + abort(); + + case SNMP_OP_COMMIT: + switch (which) { + + case LEAF_begemotNtpHost: + string_commit(ctx); + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNtpPort: + string_commit(ctx); + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNtpTimeout: + case LEAF_begemotNtpDebug: + return (SNMP_ERR_NOERROR); + } + abort(); + } + abort(); +} Property changes on: vendor/bsnmp/1.13/snmp_ntp/snmp_ntp.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_target/Makefile.in =================================================================== --- vendor/bsnmp/1.13/snmp_target/Makefile.in (nonexistent) +++ vendor/bsnmp/1.13/snmp_target/Makefile.in (revision 336778) @@ -0,0 +1,38 @@ +# Copyright (c) 2018 +# Hartmut Brandt. +# All rights reserved. +# +# Author: Harti Brandt +# +# $Begemot: bsnmp/trunk/snmp_ntp/Makefile.in 1487 2008-12-23 19:03:33Z brandt_h $ +# +MOD= target +SRCS= ${MOD}_tree.c target_snmp.c +DEFS= ${MOD}_tree.def +BMIBS= +MAN3= snmp_target.3 +MANFILTER= sed -e 's%@MODPATH@%${LIBDIR}/%g' \ + -e 's%@DEFPATH@%${DEFSDIR}/%g' \ + -e 's%@MIBSPATH@%${MIBSDIR}/%g' + +XSYM= snmpTargetMIB snmpNotificationMIB snmpUDPDomain snmpNotifyType + +LIB= snmp_${MOD}.la +SHLIB_MAJOR= 6 +SHLIB_MINOR= 0 + +CFLAGS+= -I$(srcdir) -I$(srcdir)/../lib -I$(builddir) -I$(top_builddir) -I$(srcdir)/../snmpd + +CLEANFILES += ${MOD}_oid.h ${MOD}_tree.c ${MOD}_tree.h *.3out + +# for bootstrapping +GENSNMPTREE= $(builddir)/../gensnmptree/gensnmptree -I${srcdir}/../lib + +$(LIB): ${MOD}_oid.h ${MOD}_tree.h $(SRCS:.c=.lo) + $(LIBTOOL) --mode=link $(CC) $(LDLAGS) -module -o $@ $(SRCS:.c=.lo) -rpath $(libdir) -version-info $(SHLIB_MAJOR):$(SHLIB_MINOR) + +${MOD}_oid.h: ${MOD}_tree.def + ${GENSNMPTREE} <${srcdir}/${MOD}_tree.def -e ${XSYM} >$@ + +${MOD}_tree.h ${MOD}_tree.c : ${MOD}_tree.def + ${GENSNMPTREE} <${srcdir}/${MOD}_tree.def -l -p ${MOD}_ Property changes on: vendor/bsnmp/1.13/snmp_target/Makefile.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_target/snmp_target.3 =================================================================== --- vendor/bsnmp/1.13/snmp_target/snmp_target.3 (nonexistent) +++ vendor/bsnmp/1.13/snmp_target/snmp_target.3 (revision 336778) @@ -0,0 +1,204 @@ +.\"- +.\" Copyright (C) 2010 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by Shteryana Sotirova Shopova under +.\" sponsorship from the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: head/contrib/bsnmp/snmp_target/snmp_target.3 310648 2016-12-27 23:32:54Z ngie $ +.\" +.Dd December 16, 2010 +.Dt SNMP_TARGET 3 +.Os +.Sh NAME +.Nm snmp_target +.Nd "Target addresses and notifications module for" +.Xr bsnmpd 1 +.Sh LIBRARY +.Pq begemotSnmpdModulePath."target" = "/usr/lib/snmp_target.so" +.Sh DESCRIPTION +The +.Nm snmp_target +module implements SNMPv3 Management Target MIB and basic functionality from +Notification MIB as defined in RFC 3413. The module is used to manage the +internal list of SNMPv3 notification target addresses in +.Nm bsnmpd +and their associated transport and encapsulation parameters. +The module must be loaded for +.Nm bsnmpd +to send SNMPv3 Trap-PDUs to the configured notification target addresses. +.Sh IMPLEMENTATION NOTES +A short description of the objects implemented in the module follows. +.Bl -tag -width "XXXXXXXXX" +.It Va snmpTargetSpinLock +An advisory lock used to coordinate several Command Generator Applications when +altering the SNMP Target addresses and their associated parameters. +.It Va snmpTargetAddrTable +The table contains the transport addresses to be used in generation of SNMP +messages. +The table contains the following objects +.Bl -tag -width ".It Va snmpTargetAddrName" +.It Va snmpTargetAddrName +A unique local identifier used as entry key. Not accessible for GET or SET +operations. +.It Va snmpTargetAddrTDomain +The transport domain of the target address. Currently only UDP over IPv4 is +supported and any attempt to SET the value of this object will return an +"inconsistentValue" error. Additional transport domains will be supported +in future via the object definitions in TRANSPORT-ADDRESS-MIB (RFC 3419). +.It Va snmpTargetAddrTAddress +The transport address of this entry interpreted within the context of the value +of +.Va snmpTargetAddrTDomain . +For UDP over IPv4, this is a 6-byte long octetstring, with the first 4 bytes +representing the IPv4 address and the last 2 bytes the UDP port number in +network-byte order. +.It Va snmpTargetAddrTimeout +The value of this object is only relevant when the receiver of the SNMP +message is to send an acknowledgment that the message was received, i.e +for SNMP notifications it is relevant if the notification is SNMP Inform +rather than SNMP Trap. Currently +.Nm bsnmpd +supports only SNMP Trap notifications, so the value of this object is +meaningless. +.It Va snmpTargetAddrRetryCount +As with +.Va snmpTargetAddrTimeout +the value of this object currently is meaningless. +.It Va snmpTargetAddrTagList +A list of human-readable tag values used to select target addresses for a +particular operation. Recognized ASCII delimiting characters between tags are +space (0x20), tab (0x20), carriage return (0xOD) and line feed (0x0A). +.It Va snmpTargetAddrParams +The value of this object contains the value of a key in snmpTargetParamsTable +containing SNMP parameters used when generating messages to this transport +address. +.It Va snmpTargetAddrStorageType +This column always has either of two values. Entries created via +.Nm bsnmpd's +configuration file always have this column set to readOnly (5) and +it is not possible to modify those entries. Entries created by Command Generator +Applications always have this column set to volatile(2) and such entries are +lost when the module is restarted. A SET operation on this column is not +allowed. +.It Va snmpTargetAddrRowStatus +This column is used to create new target address entries or delete existing ones +from the table. +.El +.It Va snmpTargetParamsTable +The table contains the target information to be used in generation of SNMP +messages. +The table contains the following objects +.Bl -tag -width ".It Va snmpTargetParamsName" +.It Va snmpTargetParamsName +A unique local identifier used as entry key. Not accessible for GET or SET +operations. +.It Va snmpTargetParamsMPModel +The Message Processing Model to be used when generating SNMP PDUs using this +entry. Supported values are 0 for SNMPv1, 1 for SNMPv2c and 3 for SNMPv3. +.It Va snmpTargetParamsSecurityModel +The Security Model to be used when generating SNMP PDUs using this entry. +Supported values are 1 for SNMPv1, 2 for SNMPv2c and 3 for SNMPv3 User-Based +Security Model. +.It Va snmpTargetParamsSecurityName +The securityName which identifies the Principal on whose behalf SNMP PDUs +will be generated using this entry. For SNMPv1 and SNMPv2c this is the +name of a community configured in +.Nm bsnmpd , +and for SNMPv3 USM, this is the name of an existing user configured via the +.Nm snmp_usm +module. +.It Va snmpTargetParamsSecurityLevel +The Security Level to be used when generating SNMP PDUs using this entry. +Supported values are noAuthNoPriv(1) for plain-text PDUs with no authentication, +authNoPriv(2) for authenticated plain-text PDUs and authPriv(3) for encrypted +PDUs. +.It Va snmpTargetParamsStorageType +As with +.Va snmpTargetAddrStorageType +this column always has either of two values. Entries created via +.Nm bsnmpd's +configuration file always have this column set to readOnly (5), while entries +created by Command Generator Applications always have this column set to +volatile(2). A SET operation on this column is not allowed. +.It Va snmpTargetParamsRowStatus +This column is used to create new target address parameters entries or delete +existing ones from the table. +.El +.It Va snmpNotifyTable +The table is used to select the management targets which should receive SNMP +notifications. +The table contains the following objects +.Bl -tag -width ".It Va snmpNotifyName" +.It Va snmpNotifyName +A unique local identifier used as entry key. Not accessible for GET or SET +operations. +.It Va snmpNotifyTag +This object contains a single tag value used to select target addresses from +the +.Va snmpTargetAddrTable +to which the notifications will be send. +.It Va snmpNotifyType +The type of SNMP notifications that will be send to the target addresses +matching the corresponding +.Va snmpNotifyTag . +Possible values are Trap (1) or Inform (2). Currently only SNMP Traps are +supported and any attempt to SET the value of this object will return an +"inconsistentValue" error. +.It Va snmpNotifyStorageType +Again this column always has either of two values. Entries created via +.Nm bsnmpd's +configuration file always have this column set to readOnly (5), while entries +created by Command Generator Applications always have this column set to +volatile(2). A SET operation on this column is not allowed. +.It Va snmpNotifyRowStatus +This column is used to create new notification target entries or delete existing +ones from the table. +.El +.El +.Pp +The +.Va snmpNotifyFilterProfileTable +and +.Va snmpNotifyFilterTable +tables from the SNMP-NOTIFICATION-MIB are not supported by the module. +Notification filtering is supported via the +.Xr snmp_vacm 3 +module instead. +.Sh FILES +.Bl -tag -width "XXXXXXXXX" +.It Pa /usr/share/snmp/defs/target_tree.def +The description of the MIB tree implemented by +.Nm . +.El +.Sh SEE ALSO +.Xr bsnmpd 1 , +.Xr gensnmptree 1 , +.Xr snmpmod 3 , +.Xr snmp_usm 3 , +.Xr snmp_vacm 3 +.Sh STANDARDS +IETF RFC 3413 +.Sh AUTHORS +.An Shteryana Shopova Aq syrinx@FreeBSD.org Property changes on: vendor/bsnmp/1.13/snmp_target/snmp_target.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_target/target_snmp.c =================================================================== --- vendor/bsnmp/1.13/snmp_target/target_snmp.c (nonexistent) +++ vendor/bsnmp/1.13/snmp_target/target_snmp.c (revision 336778) @@ -0,0 +1,842 @@ +/*- + * Copyright (c) 2010,2018 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Shteryana Sotirova Shopova under + * sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/contrib/bsnmp/snmp_target/target_snmp.c 272878 2014-10-10 00:26:28Z syrinx $ + */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "asn1.h" +#include "snmp.h" +#include "snmpmod.h" +#include "lib/snmptc.h" + +#define SNMPTREE_TYPES +#include "target_tree.h" +#include "target_oid.h" + +static struct lmodule *target_module; +/* For the registration. */ +static const struct asn_oid oid_target = OIDX_snmpTargetMIB; +static const struct asn_oid oid_notification = OIDX_snmpNotificationMIB; + +static uint reg_target; +static uint reg_notification; + +static int32_t target_lock; + +static const struct asn_oid oid_udp_domain = OIDX_snmpUDPDomain; + +/* + * Internal datastructures and forward declarations. + */ +static void target_append_index(struct asn_oid *, uint, + const char *); +static int target_decode_index(const struct asn_oid *, uint, + char *); +static struct target_address *target_get_address(const struct asn_oid *, + uint); +static struct target_address *target_get_next_address(const struct asn_oid *, + uint); +static struct target_param *target_get_param(const struct asn_oid *, + uint); +static struct target_param *target_get_next_param(const struct asn_oid *, + uint); +static struct target_notify *target_get_notify(const struct asn_oid *, + uint); +static struct target_notify *target_get_next_notify(const struct asn_oid *, + uint); + +int +op_snmp_target(struct snmp_context *ctx __unused, struct snmp_value *val, + uint32_t sub, uint32_t iidx __unused, enum snmp_op op) +{ + struct snmpd_target_stats *ctx_stats; + + if (val->var.subs[sub - 1] == LEAF_snmpTargetSpinLock) { + switch (op) { + case SNMP_OP_GET: + if (++target_lock == INT32_MAX) + target_lock = 0; + val->v.integer = target_lock; + break; + case SNMP_OP_GETNEXT: + abort(); + case SNMP_OP_SET: + if (val->v.integer != target_lock) + return (SNMP_ERR_INCONS_VALUE); + break; + case SNMP_OP_ROLLBACK: + /* FALLTHROUGH */ + case SNMP_OP_COMMIT: + break; + } + return (SNMP_ERR_NOERROR); + } else if (op == SNMP_OP_SET) + return (SNMP_ERR_NOT_WRITEABLE); + + if ((ctx_stats = bsnmpd_get_target_stats()) == NULL) + return (SNMP_ERR_GENERR); + + if (op == SNMP_OP_GET) { + switch (val->var.subs[sub - 1]) { + case LEAF_snmpUnavailableContexts: + val->v.uint32 = ctx_stats->unavail_contexts; + break; + case LEAF_snmpUnknownContexts: + val->v.uint32 = ctx_stats->unknown_contexts; + break; + default: + return (SNMP_ERR_NOSUCHNAME); + } + return (SNMP_ERR_NOERROR); + } + abort(); +} + +int +op_snmp_target_addrs(struct snmp_context *ctx __unused, struct snmp_value *val, + uint32_t sub, uint32_t iidx __unused, enum snmp_op op) +{ + char aname[SNMP_ADM_STR32_SIZ]; + struct target_address *addrs; + + switch (op) { + case SNMP_OP_GET: + if ((addrs = target_get_address(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if ((addrs = target_get_next_address(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + target_append_index(&val->var, sub, addrs->name); + break; + + case SNMP_OP_SET: + if ((addrs = target_get_address(&val->var, sub)) == NULL && + (val->var.subs[sub - 1] != LEAF_snmpTargetAddrRowStatus || + val->v.integer != RowStatus_createAndWait)) + return (SNMP_ERR_NOSUCHNAME); + + if (addrs != NULL) { + if (community != COMM_INITIALIZE && + addrs->type == StorageType_readOnly) + return (SNMP_ERR_NOT_WRITEABLE); + if (addrs->status == RowStatus_active && + val->v.integer != RowStatus_destroy) + return (SNMP_ERR_INCONS_VALUE); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_snmpTargetAddrTDomain: + return (SNMP_ERR_INCONS_VALUE); + case LEAF_snmpTargetAddrTAddress: + if (val->v.octetstring.len != SNMP_UDP_ADDR_SIZ) + return (SNMP_ERR_INCONS_VALUE); + ctx->scratch->ptr1 = malloc(SNMP_UDP_ADDR_SIZ); + if (ctx->scratch->ptr1 == NULL) + return (SNMP_ERR_GENERR); + memcpy(ctx->scratch->ptr1, addrs->address, + SNMP_UDP_ADDR_SIZ); + memcpy(addrs->address, val->v.octetstring.octets, + SNMP_UDP_ADDR_SIZ); + break; + + case LEAF_snmpTargetAddrTagList: + if (val->v.octetstring.len >= SNMP_TAG_SIZ) + return (SNMP_ERR_INCONS_VALUE); + ctx->scratch->int1 = strlen(addrs->taglist) + 1; + ctx->scratch->ptr1 = malloc(ctx->scratch->int1); + if (ctx->scratch->ptr1 == NULL) + return (SNMP_ERR_GENERR); + strlcpy(ctx->scratch->ptr1, addrs->taglist, + ctx->scratch->int1); + memcpy(addrs->taglist, val->v.octetstring.octets, + val->v.octetstring.len); + addrs->taglist[val->v.octetstring.len] = '\0'; + break; + + case LEAF_snmpTargetAddrParams: + if (val->v.octetstring.len >= SNMP_ADM_STR32_SIZ) + return (SNMP_ERR_INCONS_VALUE); + ctx->scratch->int1 = strlen(addrs->paramname) + 1; + ctx->scratch->ptr1 = malloc(ctx->scratch->int1); + if (ctx->scratch->ptr1 == NULL) + return (SNMP_ERR_GENERR); + strlcpy(ctx->scratch->ptr1, addrs->paramname, + ctx->scratch->int1); + memcpy(addrs->paramname, val->v.octetstring.octets, + val->v.octetstring.len); + addrs->paramname[val->v.octetstring.len] = '\0'; + break; + + case LEAF_snmpTargetAddrRetryCount: + ctx->scratch->int1 = addrs->retry; + addrs->retry = val->v.integer; + break; + + case LEAF_snmpTargetAddrTimeout: + ctx->scratch->int1 = addrs->timeout; + addrs->timeout = val->v.integer / 10; + break; + + case LEAF_snmpTargetAddrStorageType: + return (SNMP_ERR_INCONS_VALUE); + + case LEAF_snmpTargetAddrRowStatus: + if (addrs != NULL) { + if (val->v.integer != RowStatus_active && + val->v.integer != RowStatus_destroy) + return (SNMP_ERR_INCONS_VALUE); + if (val->v.integer == RowStatus_active && + (addrs->address[0] == 0 || + strlen(addrs->taglist) == 0 || + strlen(addrs->paramname) == 0)) + return (SNMP_ERR_INCONS_VALUE); + ctx->scratch->int1 = addrs->status; + addrs->status = val->v.integer; + return (SNMP_ERR_NOERROR); + } + if (val->v.integer != RowStatus_createAndWait || + target_decode_index(&val->var, sub, aname) < 0) + return (SNMP_ERR_INCONS_VALUE); + if ((addrs = target_new_address(aname)) == NULL) + return (SNMP_ERR_GENERR); + addrs->status = RowStatus_destroy; + if (community != COMM_INITIALIZE) + addrs->type = StorageType_volatile; + else + addrs->type = StorageType_readOnly; + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + switch (val->var.subs[sub - 1]) { + case LEAF_snmpTargetAddrTAddress: + case LEAF_snmpTargetAddrTagList: + case LEAF_snmpTargetAddrParams: + free(ctx->scratch->ptr1); + break; + case LEAF_snmpTargetAddrRowStatus: + if ((addrs = target_get_address(&val->var, sub)) == NULL) + return (SNMP_ERR_GENERR); + if (val->v.integer == RowStatus_destroy) + return (target_delete_address(addrs)); + else if (val->v.integer == RowStatus_active) + return (target_activate_address(addrs)); + break; + default: + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + if ((addrs = target_get_address(&val->var, sub)) == NULL) + return (SNMP_ERR_GENERR); + + switch (val->var.subs[sub - 1]) { + case LEAF_snmpTargetAddrTAddress: + memcpy(addrs->address, ctx->scratch->ptr1, + SNMP_UDP_ADDR_SIZ); + free(ctx->scratch->ptr1); + break; + + case LEAF_snmpTargetAddrTagList: + strlcpy(addrs->taglist, ctx->scratch->ptr1, + ctx->scratch->int1); + free(ctx->scratch->ptr1); + break; + + case LEAF_snmpTargetAddrParams: + strlcpy(addrs->paramname, ctx->scratch->ptr1, + ctx->scratch->int1); + free(ctx->scratch->ptr1); + break; + + case LEAF_snmpTargetAddrRetryCount: + addrs->retry = ctx->scratch->int1; + break; + + case LEAF_snmpTargetAddrTimeout: + addrs->timeout = ctx->scratch->int1; + break; + + case LEAF_snmpTargetAddrRowStatus: + if (ctx->scratch->int1 == RowStatus_destroy) + return (target_delete_address(addrs)); + break; + default: + break; + } + return (SNMP_ERR_NOERROR); + + default: + abort(); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_snmpTargetAddrTDomain: + return (oid_get(val, &oid_udp_domain)); + case LEAF_snmpTargetAddrTAddress: + return (string_get(val, addrs->address, SNMP_UDP_ADDR_SIZ)); + case LEAF_snmpTargetAddrTimeout: + val->v.integer = addrs->timeout; + break; + case LEAF_snmpTargetAddrRetryCount: + val->v.integer = addrs->retry; + break; + case LEAF_snmpTargetAddrTagList: + return (string_get(val, addrs->taglist, -1)); + case LEAF_snmpTargetAddrParams: + return (string_get(val, addrs->paramname, -1)); + case LEAF_snmpTargetAddrStorageType: + val->v.integer = addrs->type; + break; + case LEAF_snmpTargetAddrRowStatus: + val->v.integer = addrs->status; + break; + default: + abort(); + } + + return (SNMP_ERR_NOERROR); +} + +int +op_snmp_target_params(struct snmp_context *ctx __unused, struct snmp_value *val, + uint32_t sub, uint32_t iidx __unused, enum snmp_op op) +{ + char pname[SNMP_ADM_STR32_SIZ]; + struct target_param *param; + + switch (op) { + case SNMP_OP_GET: + if ((param = target_get_param(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if ((param = target_get_next_param(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + target_append_index(&val->var, sub, param->name); + break; + + case SNMP_OP_SET: + if ((param = target_get_param(&val->var, sub)) == NULL && + (val->var.subs[sub - 1] != LEAF_snmpTargetParamsRowStatus || + val->v.integer != RowStatus_createAndWait)) + return (SNMP_ERR_NOSUCHNAME); + + if (param != NULL) { + if (community != COMM_INITIALIZE && + param->type == StorageType_readOnly) + return (SNMP_ERR_NOT_WRITEABLE); + if (param->status == RowStatus_active && + val->v.integer != RowStatus_destroy) + return (SNMP_ERR_INCONS_VALUE); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_snmpTargetParamsMPModel: + if (val->v.integer != SNMP_MPM_SNMP_V1 && + val->v.integer != SNMP_MPM_SNMP_V2c && + val->v.integer != SNMP_MPM_SNMP_V3) + return (SNMP_ERR_INCONS_VALUE); + ctx->scratch->int1 = param->mpmodel; + param->mpmodel = val->v.integer; + break; + + case LEAF_snmpTargetParamsSecurityModel: + if (val->v.integer != SNMP_SECMODEL_SNMPv1 && + val->v.integer != SNMP_SECMODEL_SNMPv2c && + val->v.integer != SNMP_SECMODEL_USM) + return (SNMP_ERR_INCONS_VALUE); + ctx->scratch->int1 = param->sec_model; + param->sec_model = val->v.integer; + break; + + case LEAF_snmpTargetParamsSecurityName: + if (val->v.octetstring.len >= SNMP_ADM_STR32_SIZ) + return (SNMP_ERR_INCONS_VALUE); + ctx->scratch->int1 = strlen(param->secname) + 1; + ctx->scratch->ptr1 = malloc(ctx->scratch->int1); + if (ctx->scratch->ptr1 == NULL) + return (SNMP_ERR_GENERR); + strlcpy(ctx->scratch->ptr1, param->secname, + ctx->scratch->int1); + memcpy(param->secname, val->v.octetstring.octets, + val->v.octetstring.len); + param->secname[val->v.octetstring.len] = '\0'; + break; + + case LEAF_snmpTargetParamsSecurityLevel: + if (val->v.integer != SNMP_noAuthNoPriv && + val->v.integer != SNMP_authNoPriv && + val->v.integer != SNMP_authPriv) + return (SNMP_ERR_INCONS_VALUE); + ctx->scratch->int1 = param->sec_level; + param->sec_level = val->v.integer; + break; + + case LEAF_snmpTargetParamsStorageType: + return (SNMP_ERR_INCONS_VALUE); + + case LEAF_snmpTargetParamsRowStatus: + if (param != NULL) { + if (val->v.integer != RowStatus_active && + val->v.integer != RowStatus_destroy) + return (SNMP_ERR_INCONS_VALUE); + if (val->v.integer == RowStatus_active && + (param->sec_model == 0 || + param->sec_level == 0 || + strlen(param->secname) == 0)) + return (SNMP_ERR_INCONS_VALUE); + ctx->scratch->int1 = param->status; + param->status = val->v.integer; + return (SNMP_ERR_NOERROR); + } + if (val->v.integer != RowStatus_createAndWait || + target_decode_index(&val->var, sub, pname) < 0) + return (SNMP_ERR_INCONS_VALUE); + if ((param = target_new_param(pname)) == NULL) + return (SNMP_ERR_GENERR); + param->status = RowStatus_destroy; + if (community != COMM_INITIALIZE) + param->type = StorageType_volatile; + else + param->type = StorageType_readOnly; + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + switch (val->var.subs[sub - 1]) { + case LEAF_snmpTargetParamsSecurityName: + free(ctx->scratch->ptr1); + break; + case LEAF_snmpTargetParamsRowStatus: + if ((param = target_get_param(&val->var, sub)) == NULL) + return (SNMP_ERR_GENERR); + if (val->v.integer == RowStatus_destroy) + return (target_delete_param(param)); + break; + default: + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + if ((param = target_get_param(&val->var, sub)) == NULL && + (val->var.subs[sub - 1] != LEAF_snmpTargetParamsRowStatus || + val->v.integer != RowStatus_createAndWait)) + return (SNMP_ERR_GENERR); + switch (val->var.subs[sub - 1]) { + case LEAF_snmpTargetParamsMPModel: + param->mpmodel = ctx->scratch->int1; + break; + case LEAF_snmpTargetParamsSecurityModel: + param->sec_model = ctx->scratch->int1; + break; + case LEAF_snmpTargetParamsSecurityName: + strlcpy(param->secname, ctx->scratch->ptr1, + sizeof(param->secname)); + free(ctx->scratch->ptr1); + break; + case LEAF_snmpTargetParamsSecurityLevel: + param->sec_level = ctx->scratch->int1; + break; + case LEAF_snmpTargetParamsRowStatus: + if (ctx->scratch->int1 == RowStatus_destroy) + return (target_delete_param(param)); + break; + default: + break; + } + + return (SNMP_ERR_NOERROR); + + default: + abort(); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_snmpTargetParamsMPModel: + val->v.integer = param->mpmodel; + break; + case LEAF_snmpTargetParamsSecurityModel: + val->v.integer = param->sec_model; + break; + case LEAF_snmpTargetParamsSecurityName: + return (string_get(val, param->secname, -1)); + case LEAF_snmpTargetParamsSecurityLevel: + val->v.integer = param->sec_level; + break; + case LEAF_snmpTargetParamsStorageType: + val->v.integer = param->type; + break; + case LEAF_snmpTargetParamsRowStatus: + val->v.integer = param->status; + break; + default: + abort(); + } + + return (SNMP_ERR_NOERROR); +} + +int +op_snmp_notify(struct snmp_context *ctx __unused, struct snmp_value *val, + uint32_t sub, uint32_t iidx __unused, enum snmp_op op) +{ + char nname[SNMP_ADM_STR32_SIZ]; + struct target_notify *notify; + + switch (op) { + case SNMP_OP_GET: + if ((notify = target_get_notify(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if ((notify = target_get_next_notify(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + target_append_index(&val->var, sub, notify->name); + break; + + case SNMP_OP_SET: + if ((notify = target_get_notify(&val->var, sub)) == NULL && + (val->var.subs[sub - 1] != LEAF_snmpNotifyRowStatus || + val->v.integer != RowStatus_createAndGo)) + return (SNMP_ERR_NOSUCHNAME); + + if (notify != NULL) { + if (community != COMM_INITIALIZE && + notify->type == StorageType_readOnly) + return (SNMP_ERR_NOT_WRITEABLE); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_snmpNotifyTag: + if (val->v.octetstring.len >= SNMP_TAG_SIZ) + return (SNMP_ERR_INCONS_VALUE); + ctx->scratch->int1 = strlen(notify->taglist) + 1; + ctx->scratch->ptr1 = malloc(ctx->scratch->int1); + if (ctx->scratch->ptr1 == NULL) + return (SNMP_ERR_GENERR); + strlcpy(ctx->scratch->ptr1, notify->taglist, + ctx->scratch->int1); + memcpy(notify->taglist, val->v.octetstring.octets, + val->v.octetstring.len); + notify->taglist[val->v.octetstring.len] = '\0'; + break; + + case LEAF_snmpNotifyType: + /* FALLTHROUGH */ + case LEAF_snmpNotifyStorageType: + return (SNMP_ERR_INCONS_VALUE); + case LEAF_snmpNotifyRowStatus: + if (notify != NULL) { + if (val->v.integer != RowStatus_active && + val->v.integer != RowStatus_destroy) + return (SNMP_ERR_INCONS_VALUE); + ctx->scratch->int1 = notify->status; + notify->status = val->v.integer; + return (SNMP_ERR_NOERROR); + } + if (val->v.integer != RowStatus_createAndGo || + target_decode_index(&val->var, sub, nname) < 0) + return (SNMP_ERR_INCONS_VALUE); + if ((notify = target_new_notify(nname)) == NULL) + return (SNMP_ERR_GENERR); + notify->status = RowStatus_destroy; + if (community != COMM_INITIALIZE) + notify->type = StorageType_volatile; + else + notify->type = StorageType_readOnly; + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + switch (val->var.subs[sub - 1]) { + case LEAF_snmpNotifyTag: + free(ctx->scratch->ptr1); + break; + case LEAF_snmpNotifyRowStatus: + notify = target_get_notify(&val->var, sub); + if (notify == NULL) + return (SNMP_ERR_GENERR); + if (val->v.integer == RowStatus_destroy) + return (target_delete_notify(notify)); + else + notify->status = RowStatus_active; + break; + default: + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + if ((notify = target_get_notify(&val->var, sub)) == NULL) + return (SNMP_ERR_GENERR); + + switch (val->var.subs[sub - 1]) { + case LEAF_snmpNotifyTag: + strlcpy(notify->taglist, ctx->scratch->ptr1, + ctx->scratch->int1); + free(ctx->scratch->ptr1); + break; + case LEAF_snmpNotifyRowStatus: + if (ctx->scratch->int1 == RowStatus_destroy) + return (target_delete_notify(notify)); + break; + default: + break; + } + return (SNMP_ERR_NOERROR); + + default: + abort(); + } + + + switch (val->var.subs[sub - 1]) { + case LEAF_snmpNotifyTag: + return (string_get(val, notify->taglist, -1)); + case LEAF_snmpNotifyType: + val->v.integer = snmpNotifyType_trap; + break; + case LEAF_snmpNotifyStorageType: + val->v.integer = notify->type; + break; + case LEAF_snmpNotifyRowStatus: + val->v.integer = notify->status; + break; + default: + abort(); + } + + return (SNMP_ERR_NOERROR); +} + +static void +target_append_index(struct asn_oid *oid, uint sub, const char *name) +{ + uint32_t i; + + oid->len = sub + strlen(name); + for (i = 0; i < strlen(name); i++) + oid->subs[sub + i] = name[i]; +} + +static int +target_decode_index(const struct asn_oid *oid, uint sub, char *name) +{ + uint32_t i; + + if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= + SNMP_ADM_STR32_SIZ) + return (-1); + + for (i = 0; i < oid->subs[sub]; i++) + name[i] = oid->subs[sub + i + 1]; + name[i] = '\0'; + + return (0); +} + +static struct target_address * +target_get_address(const struct asn_oid *oid, uint sub) +{ + char aname[SNMP_ADM_STR32_SIZ]; + struct target_address *addrs; + + if (target_decode_index(oid, sub, aname) < 0) + return (NULL); + + for (addrs = target_first_address(); addrs != NULL; + addrs = target_next_address(addrs)) + if (strcmp(aname, addrs->name) == 0) + return (addrs); + + return (NULL); +} + +static struct target_address * +target_get_next_address(const struct asn_oid * oid, uint sub) +{ + char aname[SNMP_ADM_STR32_SIZ]; + struct target_address *addrs; + + if (oid->len - sub == 0) + return (target_first_address()); + + if (target_decode_index(oid, sub, aname) < 0) + return (NULL); + + for (addrs = target_first_address(); addrs != NULL; + addrs = target_next_address(addrs)) + if (strcmp(aname, addrs->name) == 0) + return (target_next_address(addrs)); + + return (NULL); +} + +static struct target_param * +target_get_param(const struct asn_oid *oid, uint sub) +{ + char pname[SNMP_ADM_STR32_SIZ]; + struct target_param *param; + + if (target_decode_index(oid, sub, pname) < 0) + return (NULL); + + for (param = target_first_param(); param != NULL; + param = target_next_param(param)) + if (strcmp(pname, param->name) == 0) + return (param); + + return (NULL); +} + +static struct target_param * +target_get_next_param(const struct asn_oid *oid, uint sub) +{ + char pname[SNMP_ADM_STR32_SIZ]; + struct target_param *param; + + if (oid->len - sub == 0) + return (target_first_param()); + + if (target_decode_index(oid, sub, pname) < 0) + return (NULL); + + for (param = target_first_param(); param != NULL; + param = target_next_param(param)) + if (strcmp(pname, param->name) == 0) + return (target_next_param(param)); + + return (NULL); +} + +static struct target_notify * +target_get_notify(const struct asn_oid *oid, uint sub) +{ + char nname[SNMP_ADM_STR32_SIZ]; + struct target_notify *notify; + + if (target_decode_index(oid, sub, nname) < 0) + return (NULL); + + for (notify = target_first_notify(); notify != NULL; + notify = target_next_notify(notify)) + if (strcmp(nname, notify->name) == 0) + return (notify); + + return (NULL); +} + +static struct target_notify * +target_get_next_notify(const struct asn_oid *oid, uint sub) +{ + char nname[SNMP_ADM_STR32_SIZ]; + struct target_notify *notify; + + if (oid->len - sub == 0) + return (target_first_notify()); + + if (target_decode_index(oid, sub, nname) < 0) + return (NULL); + + for (notify = target_first_notify(); notify != NULL; + notify = target_next_notify(notify)) + if (strcmp(nname, notify->name) == 0) + return (target_next_notify(notify)); + + return (NULL); +} + +static int +target_init(struct lmodule *mod, int argc __unused, char *argv[] __unused) +{ + target_module = mod; + target_lock = random(); + + return (0); +} + + +static int +target_fini(void) +{ + target_flush_all(); + or_unregister(reg_target); + or_unregister(reg_notification); + + return (0); +} + +static void +target_start(void) +{ + reg_target = or_register(&oid_target, + "The MIB module for managing SNMP Management Targets.", + target_module); + reg_notification = or_register(&oid_notification, + "The MIB module for configuring generation of SNMP notifications.", + target_module); +} + +static void +target_dump(void) +{ + /* XXX: dump the module stats & list of mgmt targets */ +} + +const char target_comment[] = \ +"This module implements SNMP Management Target MIB Module defined in RFC 3413."; + +const struct snmp_module config = { + .comment = target_comment, + .init = target_init, + .fini = target_fini, + .start = target_start, + .tree = target_ctree, + .dump = target_dump, + .tree_size = target_CTREE_SIZE, +}; Property changes on: vendor/bsnmp/1.13/snmp_target/target_snmp.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_target/target_tree.def =================================================================== --- vendor/bsnmp/1.13/snmp_target/target_tree.def (nonexistent) +++ vendor/bsnmp/1.13/snmp_target/target_tree.def (revision 336778) @@ -0,0 +1,87 @@ +#- +# Copyright (C) 2010 The FreeBSD Foundation +# All rights reserved. +# +# This software was developed by Shteryana Sotirova Shopova under +# sponsorship from the FreeBSD Foundation. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +include "tc.def" + +(1 internet + (6 snmpV2 + (1 snmpDomains + (1 snmpUDPDomain + ) + ) + (3 snmpModules + (12 snmpTargetMIB + (1 snmpTargetObjects + (1 snmpTargetSpinLock INTEGER op_snmp_target GET SET) + (2 snmpTargetAddrTable + (1 snmpTargetAddrEntry : OCTETSTRING op_snmp_target_addrs + (1 snmpTargetAddrName OCTETSTRING) + (2 snmpTargetAddrTDomain OID GET SET) + (3 snmpTargetAddrTAddress OCTETSTRING | TAddress GET SET) + (4 snmpTargetAddrTimeout INTEGER GET SET) + (5 snmpTargetAddrRetryCount INTEGER GET SET) + (6 snmpTargetAddrTagList OCTETSTRING | SnmpTagList GET SET) + (7 snmpTargetAddrParams OCTETSTRING GET SET) + (8 snmpTargetAddrStorageType StorageType GET SET) + (9 snmpTargetAddrRowStatus RowStatus GET SET) + ) + ) + (3 snmpTargetParamsTable + (1 snmpTargetParamsEntry : OCTETSTRING op_snmp_target_params + (1 snmpTargetParamsName OCTETSTRING) + (2 snmpTargetParamsMPModel INTEGER GET SET) + (3 snmpTargetParamsSecurityModel INTEGER GET SET) + (4 snmpTargetParamsSecurityName OCTETSTRING | SnmpAdminString GET SET) + (5 snmpTargetParamsSecurityLevel ENUM ( 1 noAuthNoPriv 2 authNoPriv 3 authPriv ) GET SET) + (6 snmpTargetParamsStorageType StorageType GET SET) + (7 snmpTargetParamsRowStatus RowStatus GET SET) + ) + ) + (4 snmpUnavailableContexts COUNTER op_snmp_target GET) + (5 snmpUnknownContexts COUNTER op_snmp_target GET) + ) + ) + (13 snmpNotificationMIB + (1 snmpNotifyObjects + (1 snmpNotifyTable + (1 snmpNotifyEntry : OCTETSTRING op_snmp_notify + (1 snmpNotifyName OCTETSTRING) + (2 snmpNotifyTag OCTETSTRING | SnmpTagValue GET SET) + (3 snmpNotifyType ENUM ( 1 trap 2 inform ) GET SET) + (4 snmpNotifyStorageType StorageType GET SET) + (5 snmpNotifyRowStatus RowStatus GET SET) + ) + ) + ) + ) + ) + ) +) Property changes on: vendor/bsnmp/1.13/snmp_target/target_tree.def ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_usm/Makefile.in =================================================================== --- vendor/bsnmp/1.13/snmp_usm/Makefile.in (nonexistent) +++ vendor/bsnmp/1.13/snmp_usm/Makefile.in (revision 336778) @@ -0,0 +1,40 @@ +# Copyright (c) 2018 +# Hartmut Brandt. +# All rights reserved. +# +# Author: Harti Brandt +# +# $Begemot: bsnmp/trunk/snmp_ntp/Makefile.in 1487 2008-12-23 19:03:33Z brandt_h $ +# +MOD= usm +SRCS= ${MOD}_tree.c usm_snmp.c +DEFS= ${MOD}_tree.def +BMIBS= +MAN3= snmp_usm.3 +MANFILTER= sed -e 's%@MODPATH@%${LIBDIR}/%g' \ + -e 's%@DEFPATH@%${DEFSDIR}/%g' \ + -e 's%@MIBSPATH@%${MIBSDIR}/%g' + +XSYM= snmpUsmMIB usmNoAuthProtocol usmHMACMD5AuthProtocol \ + usmHMACSHAAuthProtocol usmNoPrivProtocol usmDESPrivProtocol \ + usmAesCfb128Protocol usmUserSecurityName + +LIB= snmp_${MOD}.la +SHLIB_MAJOR= 6 +SHLIB_MINOR= 0 + +CFLAGS+= -I$(srcdir) -I$(srcdir)/../lib -I$(builddir) -I$(top_builddir) -I$(srcdir)/../snmpd + +CLEANFILES += ${MOD}_oid.h ${MOD}_tree.c ${MOD}_tree.h *.3out + +# for bootstrapping +GENSNMPTREE= $(builddir)/../gensnmptree/gensnmptree -I${srcdir}/../lib + +$(LIB): ${MOD}_oid.h ${MOD}_tree.h $(SRCS:.c=.lo) + $(LIBTOOL) --mode=link $(CC) $(LDLAGS) -module -o $@ $(SRCS:.c=.lo) -rpath $(libdir) -version-info $(SHLIB_MAJOR):$(SHLIB_MINOR) + +${MOD}_oid.h: ${MOD}_tree.def + ${GENSNMPTREE} <${srcdir}/${MOD}_tree.def -e ${XSYM} >$@ + +${MOD}_tree.h ${MOD}_tree.c : ${MOD}_tree.def + ${GENSNMPTREE} <${srcdir}/${MOD}_tree.def -l -p ${MOD}_ Property changes on: vendor/bsnmp/1.13/snmp_usm/Makefile.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_usm/snmp_usm.3 =================================================================== --- vendor/bsnmp/1.13/snmp_usm/snmp_usm.3 (nonexistent) +++ vendor/bsnmp/1.13/snmp_usm/snmp_usm.3 (revision 336778) @@ -0,0 +1,132 @@ +.\"- +.\" Copyright (C) 2010 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by Shteryana Sotirova Shopova under +.\" sponsorship from the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: head/contrib/bsnmp/snmp_usm/snmp_usm.3 310648 2016-12-27 23:32:54Z ngie $ +.\" +.Dd September 9, 2010 +.Dt SNMP_USM 3 +.Os +.Sh NAME +.Nm snmp_usm +.Nd "user-based security module for" +.Xr bsnmpd 1 +.Sh LIBRARY +.Pq begemotSnmpdModulePath."usm" = "/usr/lib/snmp_usm.so" +.Sh DESCRIPTION +The +.Nm snmp_usm +module implements SNMPv3 User-Based Security Model MIB as defined in RFC 3414. +The module is used to manage the internal list of SNMPv3 USM active users in +.Nm bsnmpd . +The module must be loaded for +.Nm bsnmpd +to receive and process SNMPv3 USM PDUs correctly. +.Sh IMPLEMENTATION NOTES +A short description of the objects in the MIB follows. +.Bl -tag -width "XXXXXXXXX" +.It Va usmStats +The subtree contains statistics for the User-based Security Model PDU processing. +The statistics are reset each time the module is loaded. +.It Va usmUserSpinLock +An advisory lock used to coordinate several Command Generator Applications when +altering the SNMP USM users. +.It Va usmUserTable +The table contains all SNMP USM users configured in +.Nm bsnmpd . +The table contains the following objects +.Bl -tag -width ".It Va usmUserEngineID" +.It Va usmUserEngineID +An SNMP engine's administratively-unique identifier. Must be set to the same +Engine ID as +.Nm bsnmpd +so that the user will actually be allowed to communicate with the daemon. +The column is used as entry key and is not accessible for GET or SET operations. +.It Va usmUserName +The USM user name. The second entry key, again not accessible for GET or SET +operations. +.It Va usmUserSecurityName +The column has the exact same value as the +.Va usmUserName +column, however is accessible for GET operations. +.It Va usmUserCloneFrom +A GET on this column will return an empty OID. SET operations are currently not +supported. +.It Va usmUserAuthProtocol +The value of this column contains the OID corresponding to the authentication +protocol used by the USM user. The following protocols and their OIDs are known to +.Nm +module +.Bl -tag -width ".It Va NoAuthProtocol" +.It NoAuthProtocol 1.3.6.1.6.3.10.1.1.1 +.It HMACMD5AuthProtocol 1.3.6.1.6.3.10.1.1.2 +.It HMACSHAAuthProtocol 1.3.6.1.6.3.10.1.1.3 +.El +.It Va usmUserAuthKeyChange , Va usmUserOwnAuthKeyChange +These columns may be used to change the user's authentication key. +.It Va usmUserPrivProtocol +The value of this column contains the OID corresponding to the privacy +protocol used by the USM user. The following protocols and their OIDs are known to +.Nm +module +.Bl -tag -width ".It Va NoPrivProtocol" +.It NoPrivProtocol 1.3.6.1.6.3.10.1.2.1 +.It DESPrivProtoco 1.3.6.1.6.3.10.1.2.2 +.It AesCfb128Protocol 1.3.6.1.6.3.10.1.2.4 +.El +.It Va usmUserPrivKeyChange , Va usmUserOwnPrivKeyChange +These columns may be used to change the user's privacy key. +.It Va usmUserPublic +An arbitrary octet string that may be modified to confirm a SET operation on any +of the columns was successful. +.It Va usmUserStorageType +This column always has either of two values. Entries created via +.Nm bsnmpd's +configuration file always have this column set to readOnly (5) and +it is not possible to modify those entries. Entries created by Command Generator +Applications always have this column set to volatile(2) and such entries are +lost when the module is restarted. A SET operation on this column is not +allowed. +.It Va usmUserStatus +This column is used to create new USM user entries or delete existing ones from +the table. +.El +.El +.Sh FILES +.Bl -tag -width "XXXXXXXXX" +.It Pa /usr/share/snmp/defs/usm_tree.def +The description of the MIB tree implemented by +.Nm . +.El +.Sh SEE ALSO +.Xr bsnmpd 1 , +.Xr gensnmptree 1 , +.Xr snmpmod 3 +.Sh STANDARDS +IETF RFC 3414 +.Sh AUTHORS +.An Shteryana Shopova Aq syrinx@FreeBSD.org Property changes on: vendor/bsnmp/1.13/snmp_usm/snmp_usm.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_usm/usm_snmp.c =================================================================== --- vendor/bsnmp/1.13/snmp_usm/usm_snmp.c (nonexistent) +++ vendor/bsnmp/1.13/snmp_usm/usm_snmp.c (revision 336778) @@ -0,0 +1,620 @@ +/*- + * Copyright (c) 2010 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Shteryana Sotirova Shopova under + * sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/contrib/bsnmp/snmp_usm/usm_snmp.c 311394 2017-01-05 09:46:36Z ngie $ + */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "asn1.h" +#include "snmp.h" +#include "snmpmod.h" +#include "lib/snmptc.h" + +#define SNMP_TREETYPES +#include "usm_tree.h" +#include "usm_oid.h" + +static struct lmodule *usm_module; +/* For the registration. */ +static const struct asn_oid oid_usm = OIDX_snmpUsmMIB; + +static const struct asn_oid oid_usmNoAuthProtocol = OIDX_usmNoAuthProtocol; +static const struct asn_oid oid_usmHMACMD5AuthProtocol = \ + OIDX_usmHMACMD5AuthProtocol; +static const struct asn_oid oid_usmHMACSHAAuthProtocol = \ + OIDX_usmHMACSHAAuthProtocol; + +static const struct asn_oid oid_usmNoPrivProtocol = OIDX_usmNoPrivProtocol; +static const struct asn_oid oid_usmDESPrivProtocol = OIDX_usmDESPrivProtocol; +static const struct asn_oid oid_usmAesCfb128Protocol = OIDX_usmAesCfb128Protocol; + +static const struct asn_oid oid_usmUserSecurityName = OIDX_usmUserSecurityName; + +/* The registration. */ +static uint reg_usm; + +static int32_t usm_lock; + +static struct usm_user * usm_get_user(const struct asn_oid *, uint); +static struct usm_user * usm_get_next_user(const struct asn_oid *, uint); +static void usm_append_userindex(struct asn_oid *, uint, + const struct usm_user *); +static int usm_user_index_decode(const struct asn_oid *, uint, uint8_t *, + uint32_t *, char *); + +int +op_usm_stats(struct snmp_context *ctx __unused, struct snmp_value *val, + uint32_t sub __unused, uint32_t iidx __unused, enum snmp_op op) +{ + struct snmpd_usmstat *usmstats; + + if (op == SNMP_OP_SET) + return (SNMP_ERR_NOT_WRITEABLE); + + if ((usmstats = bsnmpd_get_usm_stats()) == NULL) + return (SNMP_ERR_GENERR); + + if (op == SNMP_OP_GET) { + switch (val->var.subs[sub - 1]) { + case LEAF_usmStatsUnsupportedSecLevels: + val->v.uint32 = usmstats->unsupported_seclevels; + break; + case LEAF_usmStatsNotInTimeWindows: + val->v.uint32 = usmstats->not_in_time_windows; + break; + case LEAF_usmStatsUnknownUserNames: + val->v.uint32 = usmstats->unknown_users; + break; + case LEAF_usmStatsUnknownEngineIDs: + val->v.uint32 = usmstats->unknown_engine_ids; + break; + case LEAF_usmStatsWrongDigests: + val->v.uint32 = usmstats->wrong_digests; + break; + case LEAF_usmStatsDecryptionErrors: + val->v.uint32 = usmstats->decrypt_errors; + break; + default: + return (SNMP_ERR_NOSUCHNAME); + } + return (SNMP_ERR_NOERROR); + } + abort(); +} + +int +op_usm_lock(struct snmp_context *ctx __unused, struct snmp_value *val, + uint32_t sub, uint32_t iidx __unused, enum snmp_op op) +{ + if (val->var.subs[sub - 1] != LEAF_usmUserSpinLock) + return (SNMP_ERR_NOSUCHNAME); + + switch (op) { + case SNMP_OP_GET: + if (++usm_lock == INT32_MAX) + usm_lock = 0; + val->v.integer = usm_lock; + break; + case SNMP_OP_GETNEXT: + abort(); + case SNMP_OP_SET: + if (val->v.integer != usm_lock) + return (SNMP_ERR_INCONS_VALUE); + break; + case SNMP_OP_ROLLBACK: + /* FALLTHROUGH */ + case SNMP_OP_COMMIT: + break; + } + + return (SNMP_ERR_NOERROR); +} + +int +op_usm_users(struct snmp_context *ctx, struct snmp_value *val, + uint32_t sub, uint32_t iidx __unused, enum snmp_op op) +{ + uint32_t elen; + struct usm_user *uuser, *clone; + char uname[SNMP_ADM_STR32_SIZ]; + uint8_t eid[SNMP_ENGINE_ID_SIZ]; + + switch (op) { + case SNMP_OP_GET: + if ((uuser = usm_get_user(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if ((uuser = usm_get_next_user(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + usm_append_userindex(&val->var, sub, uuser); + break; + + case SNMP_OP_SET: + if ((uuser = usm_get_user(&val->var, sub)) == NULL && + val->var.subs[sub - 1] != LEAF_usmUserStatus && + val->var.subs[sub - 1] != LEAF_usmUserCloneFrom) + return (SNMP_ERR_NOSUCHNAME); + + /* + * XXX (ngie): need to investigate the MIB to determine how + * this is possible given some of the transitions below. + */ + if (community != COMM_INITIALIZE && + uuser != NULL && uuser->type == StorageType_readOnly) + return (SNMP_ERR_NOT_WRITEABLE); + + switch (val->var.subs[sub - 1]) { + case LEAF_usmUserSecurityName: + return (SNMP_ERR_NOT_WRITEABLE); + + case LEAF_usmUserCloneFrom: + if (uuser != NULL || usm_user_index_decode(&val->var, + sub, eid, &elen, uname) < 0 || + !(asn_is_suboid(&oid_usmUserSecurityName, &val->v.oid))) + return (SNMP_ERR_WRONG_VALUE); + if ((clone = usm_get_user(&val->v.oid, sub)) == NULL) + return (SNMP_ERR_INCONS_VALUE); + if ((uuser = usm_new_user(eid, elen, uname)) == NULL) + return (SNMP_ERR_GENERR); + uuser->status = RowStatus_notReady; + if (community != COMM_INITIALIZE) + uuser->type = StorageType_volatile; + else + uuser->type = StorageType_readOnly; + + uuser->suser.auth_proto = clone->suser.auth_proto; + uuser->suser.priv_proto = clone->suser.priv_proto; + memcpy(uuser->suser.auth_key, clone->suser.auth_key, + sizeof(uuser->suser.auth_key)); + memcpy(uuser->suser.priv_key, clone->suser.priv_key, + sizeof(uuser->suser.priv_key)); + ctx->scratch->int1 = RowStatus_createAndWait; + break; + + case LEAF_usmUserAuthProtocol: + ctx->scratch->int1 = uuser->suser.auth_proto; + if (asn_compare_oid(&oid_usmNoAuthProtocol, + &val->v.oid) == 0) + uuser->suser.auth_proto = SNMP_AUTH_NOAUTH; + else if (asn_compare_oid(&oid_usmHMACMD5AuthProtocol, + &val->v.oid) == 0) + uuser->suser.auth_proto = SNMP_AUTH_HMAC_MD5; + else if (asn_compare_oid(&oid_usmHMACSHAAuthProtocol, + &val->v.oid) == 0) + uuser->suser.auth_proto = SNMP_AUTH_HMAC_SHA; + else + return (SNMP_ERR_WRONG_VALUE); + break; + + case LEAF_usmUserAuthKeyChange: + case LEAF_usmUserOwnAuthKeyChange: + if (val->var.subs[sub - 1] == + LEAF_usmUserOwnAuthKeyChange && + (usm_user == NULL || strcmp(uuser->suser.sec_name, + usm_user->suser.sec_name) != 0)) + return (SNMP_ERR_NO_ACCESS); + if (val->v.octetstring.len > SNMP_AUTH_KEY_SIZ) + return (SNMP_ERR_INCONS_VALUE); + ctx->scratch->ptr1 = malloc(SNMP_AUTH_KEY_SIZ); + if (ctx->scratch->ptr1 == NULL) + return (SNMP_ERR_GENERR); + memcpy(ctx->scratch->ptr1, uuser->suser.auth_key, + SNMP_AUTH_KEY_SIZ); + memcpy(uuser->suser.auth_key, val->v.octetstring.octets, + val->v.octetstring.len); + break; + + case LEAF_usmUserPrivProtocol: + ctx->scratch->int1 = uuser->suser.priv_proto; + if (asn_compare_oid(&oid_usmNoPrivProtocol, + &val->v.oid) == 0) + uuser->suser.priv_proto = SNMP_PRIV_NOPRIV; + else if (asn_compare_oid(&oid_usmDESPrivProtocol, + &val->v.oid) == 0) + uuser->suser.priv_proto = SNMP_PRIV_DES; + else if (asn_compare_oid(&oid_usmAesCfb128Protocol, + &val->v.oid) == 0) + uuser->suser.priv_proto = SNMP_PRIV_AES; + else + return (SNMP_ERR_WRONG_VALUE); + break; + + case LEAF_usmUserPrivKeyChange: + case LEAF_usmUserOwnPrivKeyChange: + if (val->var.subs[sub - 1] == + LEAF_usmUserOwnPrivKeyChange && + (usm_user == NULL || strcmp(uuser->suser.sec_name, + usm_user->suser.sec_name) != 0)) + return (SNMP_ERR_NO_ACCESS); + if (val->v.octetstring.len > SNMP_PRIV_KEY_SIZ) + return (SNMP_ERR_INCONS_VALUE); + ctx->scratch->ptr1 = malloc(SNMP_PRIV_KEY_SIZ); + if (ctx->scratch->ptr1 == NULL) + return (SNMP_ERR_GENERR); + memcpy(ctx->scratch->ptr1, uuser->suser.priv_key, + sizeof(uuser->suser.priv_key)); + memcpy(uuser->suser.priv_key, val->v.octetstring.octets, + val->v.octetstring.len); + break; + + case LEAF_usmUserPublic: + if (val->v.octetstring.len > SNMP_ADM_STR32_SIZ) + return (SNMP_ERR_INCONS_VALUE); + if (uuser->user_public_len > 0) { + ctx->scratch->ptr2 = + malloc(uuser->user_public_len); + if (ctx->scratch->ptr2 == NULL) + return (SNMP_ERR_GENERR); + memcpy(ctx->scratch->ptr2, uuser->user_public, + uuser->user_public_len); + ctx->scratch->int2 = uuser->user_public_len; + } + if (val->v.octetstring.len > 0) { + memcpy(uuser->user_public, + val->v.octetstring.octets, + val->v.octetstring.len); + uuser->user_public_len = val->v.octetstring.len; + } else { + memset(uuser->user_public, 0, + sizeof(uuser->user_public)); + uuser->user_public_len = 0; + } + break; + + case LEAF_usmUserStorageType: + return (SNMP_ERR_INCONS_VALUE); + + case LEAF_usmUserStatus: + if (uuser == NULL) { + if (val->v.integer != RowStatus_createAndWait || + usm_user_index_decode(&val->var, sub, eid, + &elen, uname) < 0) + return (SNMP_ERR_INCONS_VALUE); + uuser = usm_new_user(eid, elen, uname); + if (uuser == NULL) + return (SNMP_ERR_GENERR); + uuser->status = RowStatus_notReady; + if (community != COMM_INITIALIZE) + uuser->type = StorageType_volatile; + else + uuser->type = StorageType_readOnly; + } else if (val->v.integer != RowStatus_active && + val->v.integer != RowStatus_destroy) + return (SNMP_ERR_INCONS_VALUE); + + uuser->status = val->v.integer; + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + switch (val->var.subs[sub - 1]) { + case LEAF_usmUserAuthKeyChange: + case LEAF_usmUserOwnAuthKeyChange: + case LEAF_usmUserPrivKeyChange: + case LEAF_usmUserOwnPrivKeyChange: + free(ctx->scratch->ptr1); + break; + case LEAF_usmUserPublic: + if (ctx->scratch->ptr2 != NULL) + free(ctx->scratch->ptr2); + break; + case LEAF_usmUserStatus: + if (val->v.integer != RowStatus_destroy) + break; + if ((uuser = usm_get_user(&val->var, sub)) == NULL) + return (SNMP_ERR_GENERR); + usm_delete_user(uuser); + break; + default: + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + if ((uuser = usm_get_user(&val->var, sub)) == NULL) + return (SNMP_ERR_GENERR); + switch (val->var.subs[sub - 1]) { + case LEAF_usmUserAuthProtocol: + uuser->suser.auth_proto = ctx->scratch->int1; + break; + case LEAF_usmUserAuthKeyChange: + case LEAF_usmUserOwnAuthKeyChange: + memcpy(uuser->suser.auth_key, ctx->scratch->ptr1, + sizeof(uuser->suser.auth_key)); + free(ctx->scratch->ptr1); + break; + case LEAF_usmUserPrivProtocol: + uuser->suser.priv_proto = ctx->scratch->int1; + break; + case LEAF_usmUserPrivKeyChange: + case LEAF_usmUserOwnPrivKeyChange: + memcpy(uuser->suser.priv_key, ctx->scratch->ptr1, + sizeof(uuser->suser.priv_key)); + free(ctx->scratch->ptr1); + break; + case LEAF_usmUserPublic: + if (ctx->scratch->ptr2 != NULL) { + memcpy(uuser->user_public, ctx->scratch->ptr2, + ctx->scratch->int2); + uuser->user_public_len = ctx->scratch->int2; + free(ctx->scratch->ptr2); + } else { + memset(uuser->user_public, 0, + sizeof(uuser->user_public)); + uuser->user_public_len = 0; + } + break; + case LEAF_usmUserCloneFrom: + case LEAF_usmUserStatus: + if (ctx->scratch->int1 == RowStatus_createAndWait) + usm_delete_user(uuser); + break; + default: + break; + } + return (SNMP_ERR_NOERROR); + + default: + abort(); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_usmUserSecurityName: + return (string_get(val, uuser->suser.sec_name, -1)); + case LEAF_usmUserCloneFrom: + memcpy(&val->v.oid, &oid_zeroDotZero, sizeof(oid_zeroDotZero)); + break; + case LEAF_usmUserAuthProtocol: + switch (uuser->suser.auth_proto) { + case SNMP_AUTH_HMAC_MD5: + memcpy(&val->v.oid, &oid_usmHMACMD5AuthProtocol, + sizeof(oid_usmHMACMD5AuthProtocol)); + break; + case SNMP_AUTH_HMAC_SHA: + memcpy(&val->v.oid, &oid_usmHMACSHAAuthProtocol, + sizeof(oid_usmHMACSHAAuthProtocol)); + break; + default: + memcpy(&val->v.oid, &oid_usmNoAuthProtocol, + sizeof(oid_usmNoAuthProtocol)); + break; + } + break; + case LEAF_usmUserAuthKeyChange: + case LEAF_usmUserOwnAuthKeyChange: + return (string_get(val, (char *)uuser->suser.auth_key, 0)); + case LEAF_usmUserPrivProtocol: + switch (uuser->suser.priv_proto) { + case SNMP_PRIV_DES: + memcpy(&val->v.oid, &oid_usmDESPrivProtocol, + sizeof(oid_usmDESPrivProtocol)); + break; + case SNMP_PRIV_AES: + memcpy(&val->v.oid, &oid_usmAesCfb128Protocol, + sizeof(oid_usmAesCfb128Protocol)); + break; + default: + memcpy(&val->v.oid, &oid_usmNoPrivProtocol, + sizeof(oid_usmNoPrivProtocol)); + break; + } + break; + case LEAF_usmUserPrivKeyChange: + case LEAF_usmUserOwnPrivKeyChange: + return (string_get(val, (char *)uuser->suser.priv_key, 0)); + case LEAF_usmUserPublic: + return (string_get(val, uuser->user_public, + uuser->user_public_len)); + case LEAF_usmUserStorageType: + val->v.integer = uuser->type; + break; + case LEAF_usmUserStatus: + val->v.integer = uuser->status; + break; + } + + return (SNMP_ERR_NOERROR); +} + +static int +usm_user_index_decode(const struct asn_oid *oid, uint sub, uint8_t *engine, + uint32_t *elen, char *uname) +{ + uint32_t i, nlen; + int uname_off; + + if (oid->subs[sub] > SNMP_ENGINE_ID_SIZ) + return (-1); + + for (i = 0; i < oid->subs[sub]; i++) + engine[i] = oid->subs[sub + i + 1]; + *elen = i; + + uname_off = sub + oid->subs[sub] + 1; + if ((nlen = oid->subs[uname_off]) >= SNMP_ADM_STR32_SIZ) + return (-1); + + for (i = 0; i < nlen; i++) + uname[i] = oid->subs[uname_off + i + 1]; + uname[nlen] = '\0'; + + return (0); +} + +static void +usm_append_userindex(struct asn_oid *oid, uint sub, + const struct usm_user *uuser) +{ + uint32_t i; + + oid->len = sub + uuser->user_engine_len + strlen(uuser->suser.sec_name); + oid->len += 2; + oid->subs[sub] = uuser->user_engine_len; + for (i = 1; i < uuser->user_engine_len + 1; i++) + oid->subs[sub + i] = uuser->user_engine_id[i - 1]; + + sub += uuser->user_engine_len + 1; + oid->subs[sub] = strlen(uuser->suser.sec_name); + for (i = 1; i <= oid->subs[sub]; i++) + oid->subs[sub + i] = uuser->suser.sec_name[i - 1]; +} + +static struct usm_user * +usm_get_user(const struct asn_oid *oid, uint sub) +{ + uint32_t enginelen; + char username[SNMP_ADM_STR32_SIZ]; + uint8_t engineid[SNMP_ENGINE_ID_SIZ]; + + if (usm_user_index_decode(oid, sub, engineid, &enginelen, username) < 0) + return (NULL); + + return (usm_find_user(engineid, enginelen, username)); +} + +static struct usm_user * +usm_get_next_user(const struct asn_oid *oid, uint sub) +{ + uint32_t enginelen; + char username[SNMP_ADM_STR32_SIZ]; + uint8_t engineid[SNMP_ENGINE_ID_SIZ]; + struct usm_user *uuser; + + if (oid->len - sub == 0) + return (usm_first_user()); + + if (usm_user_index_decode(oid, sub, engineid, &enginelen, username) < 0) + return (NULL); + + if ((uuser = usm_find_user(engineid, enginelen, username)) != NULL) + return (usm_next_user(uuser)); + + return (NULL); +} + +/* + * USM snmp module initialization hook. + * Returns 0 on success, < 0 on error. + */ +static int +usm_init(struct lmodule * mod, int argc __unused, char *argv[] __unused) +{ + usm_module = mod; + usm_lock = random(); + bsnmpd_reset_usm_stats(); + return (0); +} + +/* + * USM snmp module finalization hook. + */ +static int +usm_fini(void) +{ + usm_flush_users(); + or_unregister(reg_usm); + + return (0); +} + +/* + * USM snmp module start operation. + */ +static void +usm_start(void) +{ + reg_usm = or_register(&oid_usm, + "The MIB module for managing SNMP User-Based Security Model.", + usm_module); +} + +static void +usm_dump(void) +{ + struct usm_user *uuser; + struct snmpd_usmstat *usmstats; + const char *const authstr[] = { + "noauth", + "md5", + "sha", + NULL + }; + const char *const privstr[] = { + "nopriv", + "des", + "aes", + NULL + }; + + if ((usmstats = bsnmpd_get_usm_stats()) != NULL) { + syslog(LOG_ERR, "UnsupportedSecLevels\t\t%u", + usmstats->unsupported_seclevels); + syslog(LOG_ERR, "NotInTimeWindows\t\t%u", + usmstats->not_in_time_windows); + syslog(LOG_ERR, "UnknownUserNames\t\t%u", + usmstats->unknown_users); + syslog(LOG_ERR, "UnknownEngineIDs\t\t%u", + usmstats->unknown_engine_ids); + syslog(LOG_ERR, "WrongDigests\t\t%u", + usmstats->wrong_digests); + syslog(LOG_ERR, "DecryptionErrors\t\t%u", + usmstats->decrypt_errors); + } + + syslog(LOG_ERR, "USM users"); + for (uuser = usm_first_user(); uuser != NULL; + (uuser = usm_next_user(uuser))) + syslog(LOG_ERR, "user %s\t\t%s, %s", uuser->suser.sec_name, + authstr[uuser->suser.auth_proto], + privstr[uuser->suser.priv_proto]); +} + +const char usm_comment[] = \ +"This module implements SNMP User-based Security Model defined in RFC 3414."; + +const struct snmp_module config = { + .comment = usm_comment, + .init = usm_init, + .fini = usm_fini, + .start = usm_start, + .tree = usm_ctree, + .dump = usm_dump, + .tree_size = usm_CTREE_SIZE, +}; Property changes on: vendor/bsnmp/1.13/snmp_usm/usm_snmp.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_usm/usm_tree.def =================================================================== --- vendor/bsnmp/1.13/snmp_usm/usm_tree.def (nonexistent) +++ vendor/bsnmp/1.13/snmp_usm/usm_tree.def (revision 336778) @@ -0,0 +1,94 @@ +#- +# Copyright (C) 2010 The FreeBSD Foundation +# All rights reserved. +# +# This software was developed by Shteryana Sotirova Shopova under +# sponsorship from the FreeBSD Foundation. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +include "tc.def" + +(1 internet + (6 snmpV2 + (3 snmpModules + (10 snmpFrameworkMIB + (1 snmpFrameworkAdmin + (1 snmpAuthProtocols + (1 usmNoAuthProtocol + ) + (2 usmHMACMD5AuthProtocol + ) + (3 usmHMACSHAAuthProtocol + ) + ) + (2 snmpPrivProtocols + (1 usmNoPrivProtocol + ) + (2 usmDESPrivProtocol + ) + (4 usmAesCfb128Protocol + ) + ) + ) + ) + (15 snmpUsmMIB + (1 usmMIBObjects + (1 usmStats + (1 usmStatsUnsupportedSecLevels COUNTER op_usm_stats GET) + (2 usmStatsNotInTimeWindows COUNTER op_usm_stats GET) + (3 usmStatsUnknownUserNames COUNTER op_usm_stats GET) + (4 usmStatsUnknownEngineIDs COUNTER op_usm_stats GET) + (5 usmStatsWrongDigests COUNTER op_usm_stats GET) + (6 usmStatsDecryptionErrors COUNTER op_usm_stats GET) + ) + (2 usmUser + (1 usmUserSpinLock INTEGER op_usm_lock GET SET) + (2 usmUserTable + (1 usmUserEntry : OCTETSTRING | SnmpEngineID OCTETSTRING op_usm_users + (1 usmUserEngineID OCTETSTRING | SnmpEngineID) + (2 usmUserName OCTETSTRING) + (3 usmUserSecurityName OCTETSTRING | SnmpAdminString GET) + (4 usmUserCloneFrom OID GET SET) + (5 usmUserAuthProtocol OID GET SET) + (6 usmUserAuthKeyChange OCTETSTRING | KeyChange GET SET) + (7 usmUserOwnAuthKeyChange OCTETSTRING | KeyChange GET SET) + (8 usmUserPrivProtocol OID GET SET) + (9 usmUserPrivKeyChange OCTETSTRING | KeyChange GET SET) + (10 usmUserOwnPrivKeyChange OCTETSTRING | KeyChange GET SET) + (11 usmUserPublic OCTETSTRING GET SET) + (12 usmUserStorageType StorageType GET SET) + (13 usmUserStatus RowStatus GET SET) + ) + ) + ) + ) + ) + (20 snmpUsmAesMIB + ) + ) + ) +) + Property changes on: vendor/bsnmp/1.13/snmp_usm/usm_tree.def ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_vacm/Makefile.in =================================================================== --- vendor/bsnmp/1.13/snmp_vacm/Makefile.in (nonexistent) +++ vendor/bsnmp/1.13/snmp_vacm/Makefile.in (revision 336778) @@ -0,0 +1,38 @@ +# Copyright (c) 2018 +# Hartmut Brandt. +# All rights reserved. +# +# Author: Harti Brandt +# +# $Begemot: bsnmp/trunk/snmp_ntp/Makefile.in 1487 2008-12-23 19:03:33Z brandt_h $ +# +MOD= vacm +SRCS= ${MOD}_tree.c vacm_snmp.c +DEFS= ${MOD}_tree.def +BMIBS= +MAN3= snmp_vacm.3 +MANFILTER= sed -e 's%@MODPATH@%${LIBDIR}/%g' \ + -e 's%@DEFPATH@%${DEFSDIR}/%g' \ + -e 's%@MIBSPATH@%${MIBSDIR}/%g' + +XSYM= snmpVacmMIB vacmAccessContextMatch + +LIB= snmp_${MOD}.la +SHLIB_MAJOR= 6 +SHLIB_MINOR= 0 + +CFLAGS+= -I$(srcdir) -I$(srcdir)/../lib -I$(builddir) -I$(top_builddir) -I$(srcdir)/../snmpd + +CLEANFILES += ${MOD}_oid.h ${MOD}_tree.c ${MOD}_tree.h *.3out + +# for bootstrapping +GENSNMPTREE= $(builddir)/../gensnmptree/gensnmptree -I${srcdir}/../lib + +$(LIB): ${MOD}_oid.h ${MOD}_tree.h $(SRCS:.c=.lo) + $(LIBTOOL) --mode=link $(CC) $(LDLAGS) -module -o $@ $(SRCS:.c=.lo) -rpath $(libdir) -version-info $(SHLIB_MAJOR):$(SHLIB_MINOR) + +${MOD}_oid.h: ${MOD}_tree.def + ${GENSNMPTREE} <${srcdir}/${MOD}_tree.def -e ${XSYM} >$@ + +${MOD}_tree.h ${MOD}_tree.c : ${MOD}_tree.def + ${GENSNMPTREE} <${srcdir}/${MOD}_tree.def -l -p ${MOD}_ Property changes on: vendor/bsnmp/1.13/snmp_vacm/Makefile.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_vacm/snmp_vacm.3 =================================================================== --- vendor/bsnmp/1.13/snmp_vacm/snmp_vacm.3 (nonexistent) +++ vendor/bsnmp/1.13/snmp_vacm/snmp_vacm.3 (revision 336778) @@ -0,0 +1,94 @@ +.\"- +.\" Copyright (C) 2010 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by Shteryana Sotirova Shopova under +.\" sponsorship from the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: head/contrib/bsnmp/snmp_vacm/snmp_vacm.3 310648 2016-12-27 23:32:54Z ngie $ +.\" +.Dd October 7, 2010 +.Dt SNMP_VACM 3 +.Os +.Sh NAME +.Nm snmp_vacm +.Nd "View-based Access Control module for" +.Xr bsnmpd 1 +.Sh LIBRARY +.Pq begemotSnmpdModulePath."vacm" = "/usr/lib/snmp_vacm.so" +.Sh DESCRIPTION +The +.Nm snmp_vacm +module implements SNMPv3 View-based Access Control Model MIB as defined in +RFC 3415. The module is used to manage the internal lists of SNMPv1, v2c and +v3 user names and groups and their access rights to fetch or modify the values +of the MIB objects maintained by +.Nm bsnmpd +and the modules loaded in the daemon. +The module must be loaded for +.Nm bsnmpd +to implement proper view-based access control. If the module is not loaded, +access is granted to all configured SNMPv1 & SNMPv2c communities and SNMPv3 +USM users. +.Sh IMPLEMENTATION NOTES +An entry in any table implemented by this MIB may be created by setting the +relevant RowStatus column to createAndGo (4) - in fact, any other value for +those columns in a SET operation will cause an error. When an entry is created, +any of its columns that is not used as index, is set to the default value as +specified in the SNMP-VIEW-BASED-ACM-MIB. All entries maintained by the module +are persistent after reboot if created via +.Nm bsnmpd 's +config file, otherwise entries created via SNMP are lost after reboot. +A short description of the objects in the MIB follows. +.Bl -tag -width "XXXXXXXXX" +.It Va vacmContextTable +A read-only table that consists of a list of SNMP contexts available in +.Nm bsnmpd . +.It Va vacmSecurityToGroupTable +The table contains a list of SNMPv1, v2c and v3 user names and the groups +they belong to. +.It Va vacmAccessTable +The table contains a list of SNMP contexts to groups mappings and respectively +the names of the SNMP views under those contexts, to which users in the group +are granted read-only, read-write access or receive notifications for the +objects under the subtree in the relevant view. +.It Va vacmViewTreeFamilyTable +The table contains a list of SNMP views, i.e. entries specifying the OID of a +MIB subtree and whether access to the objects under this subtree is to be +allowed or forbidden. +.El +.Sh FILES +.Bl -tag -width "XXXXXXXXX" +.It Pa /usr/share/snmp/defs/vacm_tree.def +The description of the MIB tree implemented by +.Nm . +.El +.Sh SEE ALSO +.Xr bsnmpd 1 , +.Xr gensnmptree 1 , +.Xr snmpmod 3 +.Sh STANDARDS +IETF RFC 3415 +.Sh AUTHORS +.An Shteryana Shopova Aq syrinx@FreeBSD.org Property changes on: vendor/bsnmp/1.13/snmp_vacm/snmp_vacm.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_vacm/vacm_snmp.c =================================================================== --- vendor/bsnmp/1.13/snmp_vacm/vacm_snmp.c (nonexistent) +++ vendor/bsnmp/1.13/snmp_vacm/vacm_snmp.c (revision 336778) @@ -0,0 +1,1028 @@ +/*- + * Copyright (c) 2010,2018 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Shteryana Sotirova Shopova under + * sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/contrib/bsnmp/snmp_vacm/vacm_snmp.c 310648 2016-12-27 23:32:54Z ngie $ + */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "asn1.h" +#include "snmp.h" +#include "snmpmod.h" +#include "lib/snmptc.h" + +#define SNMPTREE_TYPES +#include "vacm_tree.h" +#include "vacm_oid.h" + +static struct lmodule *vacm_module; +/* For the registration. */ +static const struct asn_oid oid_vacm = OIDX_snmpVacmMIB; + +static uint reg_vacm; + +static int32_t vacm_lock; + +/* + * Internal datastructures and forward declarations. + */ +static void vacm_append_userindex(struct asn_oid *, + uint, const struct vacm_user *); +static int vacm_user_index_decode(const struct asn_oid *, + uint, int32_t *, char *); +static struct vacm_user *vacm_get_user(const struct asn_oid *, + uint); +static struct vacm_user *vacm_get_next_user(const struct asn_oid *, + uint); +static void vacm_append_access_rule_index(struct asn_oid *, + uint, const struct vacm_access *); +static int vacm_access_rule_index_decode(const struct asn_oid *, + uint, char *, char *, int32_t *, int32_t *); +static struct vacm_access * vacm_get_access_rule(const struct asn_oid *, + uint); +static struct vacm_access * vacm_get_next_access_rule(const struct asn_oid *, + uint); +static int vacm_view_index_decode(const struct asn_oid *, uint, + char *, struct asn_oid *); +static void vacm_append_viewindex(struct asn_oid *, uint, + const struct vacm_view *); +static struct vacm_view *vacm_get_view(const struct asn_oid *, uint); +static struct vacm_view *vacm_get_next_view(const struct asn_oid *, uint); +static struct vacm_view *vacm_get_view_by_name(u_char *, u_int); +static struct vacm_context *vacm_get_context(const struct asn_oid *, uint); +static struct vacm_context *vacm_get_next_context(const struct asn_oid *, + uint); +static void vacm_append_ctxindex(struct asn_oid *, uint, + const struct vacm_context *); + +int +op_vacm_context(struct snmp_context *ctx __unused, struct snmp_value *val, + uint32_t sub, uint32_t iidx __unused, enum snmp_op op) +{ + char cname[SNMP_ADM_STR32_SIZ]; + size_t cnamelen; + struct vacm_context *vacm_ctx; + + if (val->var.subs[sub - 1] != LEAF_vacmContextName) + abort(); + + switch (op) { + case SNMP_OP_GET: + if ((vacm_ctx = vacm_get_context(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if ((vacm_ctx = vacm_get_next_context(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + vacm_append_ctxindex(&val->var, sub, vacm_ctx); + break; + + case SNMP_OP_SET: + if ((vacm_ctx = vacm_get_context(&val->var, sub)) != NULL) + return (SNMP_ERR_WRONG_VALUE); + if (community != COMM_INITIALIZE) + return (SNMP_ERR_NOT_WRITEABLE); + if (val->var.subs[sub] >= SNMP_ADM_STR32_SIZ) + return (SNMP_ERR_WRONG_VALUE); + if (index_decode(&val->var, sub, iidx, &cname, &cnamelen)) + return (SNMP_ERR_GENERR); + cname[cnamelen] = '\0'; + if ((vacm_ctx = vacm_add_context(cname, reg_vacm)) == NULL) + return (SNMP_ERR_GENERR); + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + /* FALLTHROUGH*/ + case SNMP_OP_ROLLBACK: + return (SNMP_ERR_NOERROR); + default: + abort(); + } + + return (string_get(val, vacm_ctx->ctxname, -1)); +} + +int +op_vacm_security_to_group(struct snmp_context *ctx, struct snmp_value *val, + uint32_t sub, uint32_t iidx __unused, enum snmp_op op) +{ + int32_t smodel; + char uname[SNMP_ADM_STR32_SIZ]; + struct vacm_user *user; + + switch (op) { + case SNMP_OP_GET: + if ((user = vacm_get_user(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if ((user = vacm_get_next_user(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + vacm_append_userindex(&val->var, sub, user); + break; + + case SNMP_OP_SET: + if ((user = vacm_get_user(&val->var, sub)) == NULL && + val->var.subs[sub - 1] != LEAF_vacmSecurityToGroupStatus) + return (SNMP_ERR_NOSUCHNAME); + + if (user != NULL) { + if (community != COMM_INITIALIZE && + user->type == StorageType_readOnly) + return (SNMP_ERR_NOT_WRITEABLE); + if (user->status == RowStatus_active && + val->v.integer != RowStatus_destroy) + return (SNMP_ERR_INCONS_VALUE); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_vacmGroupName: + ctx->scratch->ptr1 = user->group->groupname; + ctx->scratch->int1 = strlen(user->group->groupname); + return (vacm_user_set_group(user, + val->v.octetstring.octets,val->v.octetstring.len)); + + case LEAF_vacmSecurityToGroupStorageType: + return (SNMP_ERR_INCONS_VALUE); + + case LEAF_vacmSecurityToGroupStatus: + if (user == NULL) { + if (val->v.integer != RowStatus_createAndGo || + vacm_user_index_decode(&val->var, sub, + &smodel, uname) < 0) + return (SNMP_ERR_INCONS_VALUE); + user = vacm_new_user(smodel, uname); + if (user == NULL) + return (SNMP_ERR_GENERR); + user->status = RowStatus_destroy; + if (community != COMM_INITIALIZE) + user->type = StorageType_volatile; + else + user->type = StorageType_readOnly; + } else if (val->v.integer != RowStatus_active && + val->v.integer != RowStatus_destroy) + return (SNMP_ERR_INCONS_VALUE); + ctx->scratch->int1 = user->status; + user->status = val->v.integer; + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + if (val->var.subs[sub - 1] != LEAF_vacmSecurityToGroupStatus) + return (SNMP_ERR_NOERROR); + if ((user = vacm_get_user(&val->var, sub)) == NULL) + return (SNMP_ERR_GENERR); + switch (val->v.integer) { + case RowStatus_destroy: + return (vacm_delete_user(user)); + + case RowStatus_createAndGo: + user->status = RowStatus_active; + break; + + default: + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + if ((user = vacm_get_user(&val->var, sub)) == NULL) + return (SNMP_ERR_GENERR); + switch (val->var.subs[sub - 1]) { + case LEAF_vacmGroupName: + return (vacm_user_set_group(user, ctx->scratch->ptr1, + ctx->scratch->int1)); + + case LEAF_vacmSecurityToGroupStatus: + if (ctx->scratch->int1 == RowStatus_destroy) + return (vacm_delete_user(user)); + user->status = ctx->scratch->int1; + break; + + default: + break; + } + return (SNMP_ERR_NOERROR); + + default: + abort(); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_vacmGroupName: + return (string_get(val, user->group->groupname, -1)); + case LEAF_vacmSecurityToGroupStorageType: + val->v.integer = user->type; + break; + case LEAF_vacmSecurityToGroupStatus: + val->v.integer = user->status; + break; + default: + abort(); + } + + return (SNMP_ERR_NOERROR); +} + +int +op_vacm_access(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub, + uint32_t iidx __unused, enum snmp_op op) +{ + int32_t smodel, slevel; + char gname[SNMP_ADM_STR32_SIZ], cprefix[SNMP_ADM_STR32_SIZ]; + struct vacm_access *acl; + + switch (op) { + case SNMP_OP_GET: + if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if ((acl = vacm_get_next_access_rule(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + vacm_append_access_rule_index(&val->var, sub, acl); + break; + + case SNMP_OP_SET: + if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL && + val->var.subs[sub - 1] != LEAF_vacmAccessStatus) + return (SNMP_ERR_NOSUCHNAME); + if (acl != NULL && community != COMM_INITIALIZE && + acl->type == StorageType_readOnly) + return (SNMP_ERR_NOT_WRITEABLE); + + switch (val->var.subs[sub - 1]) { + case LEAF_vacmAccessContextMatch: + ctx->scratch->int1 = acl->ctx_match; + if (val->v.integer == vacmAccessContextMatch_exact) + acl->ctx_match = 1; + else if (val->v.integer == vacmAccessContextMatch_prefix) + acl->ctx_match = 0; + else + return (SNMP_ERR_WRONG_VALUE); + break; + + case LEAF_vacmAccessReadViewName: + ctx->scratch->ptr1 = acl->read_view; + acl->read_view = vacm_get_view_by_name(val->v.octetstring.octets, val->v.octetstring.len); + if (acl->read_view == NULL) { + acl->read_view = ctx->scratch->ptr1; + return (SNMP_ERR_INCONS_VALUE); + } + return (SNMP_ERR_NOERROR); + + case LEAF_vacmAccessWriteViewName: + ctx->scratch->ptr1 = acl->write_view; + if ((acl->write_view = + vacm_get_view_by_name(val->v.octetstring.octets, + val->v.octetstring.len)) == NULL) { + acl->write_view = ctx->scratch->ptr1; + return (SNMP_ERR_INCONS_VALUE); + } + break; + + case LEAF_vacmAccessNotifyViewName: + ctx->scratch->ptr1 = acl->notify_view; + if ((acl->notify_view = + vacm_get_view_by_name(val->v.octetstring.octets, + val->v.octetstring.len)) == NULL) { + acl->notify_view = ctx->scratch->ptr1; + return (SNMP_ERR_INCONS_VALUE); + } + break; + + case LEAF_vacmAccessStorageType: + return (SNMP_ERR_INCONS_VALUE); + + case LEAF_vacmAccessStatus: + if (acl == NULL) { + if (val->v.integer != RowStatus_createAndGo || + vacm_access_rule_index_decode(&val->var, + sub, gname, cprefix, &smodel, &slevel) < 0) + return (SNMP_ERR_INCONS_VALUE); + if ((acl = vacm_new_access_rule(gname, cprefix, + smodel, slevel)) == NULL) + return (SNMP_ERR_GENERR); + acl->status = RowStatus_destroy; + if (community != COMM_INITIALIZE) + acl->type = StorageType_volatile; + else + acl->type = StorageType_readOnly; + } else if (val->v.integer != RowStatus_active && + val->v.integer != RowStatus_destroy) + return (SNMP_ERR_INCONS_VALUE); + ctx->scratch->int1 = acl->status; + acl->status = val->v.integer; + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + if (val->var.subs[sub - 1] != LEAF_vacmAccessStatus) + return (SNMP_ERR_NOERROR); + if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL) + return (SNMP_ERR_GENERR); + if (val->v.integer == RowStatus_destroy) + return (vacm_delete_access_rule(acl)); + else + acl->status = RowStatus_active; + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL) + return (SNMP_ERR_GENERR); + switch (val->var.subs[sub - 1]) { + case LEAF_vacmAccessContextMatch: + acl->ctx_match = ctx->scratch->int1; + break; + case LEAF_vacmAccessReadViewName: + acl->read_view = ctx->scratch->ptr1; + break; + case LEAF_vacmAccessWriteViewName: + acl->write_view = ctx->scratch->ptr1; + break; + case LEAF_vacmAccessNotifyViewName: + acl->notify_view = ctx->scratch->ptr1; + break; + case LEAF_vacmAccessStatus: + if (ctx->scratch->int1 == RowStatus_destroy) + return (vacm_delete_access_rule(acl)); + default: + break; + } + return (SNMP_ERR_NOERROR); + + default: + abort(); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_vacmAccessContextMatch: + return (string_get(val, acl->ctx_prefix, -1)); + case LEAF_vacmAccessReadViewName: + if (acl->read_view != NULL) + return (string_get(val, acl->read_view->viewname, -1)); + else + return (string_get(val, NULL, 0)); + case LEAF_vacmAccessWriteViewName: + if (acl->write_view != NULL) + return (string_get(val, acl->write_view->viewname, -1)); + else + return (string_get(val, NULL, 0)); + case LEAF_vacmAccessNotifyViewName: + if (acl->notify_view != NULL) + return (string_get(val, acl->notify_view->viewname, -1)); + else + return (string_get(val, NULL, 0)); + case LEAF_vacmAccessStorageType: + val->v.integer = acl->type; + break; + case LEAF_vacmAccessStatus: + val->v.integer = acl->status; + break; + default: + abort(); + } + + return (SNMP_ERR_NOERROR); +} + +int +op_vacm_view_lock(struct snmp_context *ctx __unused, struct snmp_value *val, + uint32_t sub, uint32_t iidx __unused, enum snmp_op op) +{ + if (val->var.subs[sub - 1] != LEAF_vacmViewSpinLock) + return (SNMP_ERR_NOSUCHNAME); + + switch (op) { + case SNMP_OP_GET: + if (++vacm_lock == INT32_MAX) + vacm_lock = 0; + val->v.integer = vacm_lock; + break; + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_SET: + if (val->v.integer != vacm_lock) + return (SNMP_ERR_INCONS_VALUE); + break; + + case SNMP_OP_ROLLBACK: + /* FALLTHROUGH */ + case SNMP_OP_COMMIT: + break; + } + + return (SNMP_ERR_NOERROR); +} + +int +op_vacm_view(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub, + uint32_t iidx __unused, enum snmp_op op) +{ + char vname[SNMP_ADM_STR32_SIZ]; + struct asn_oid oid; + struct vacm_view *view; + + switch (op) { + case SNMP_OP_GET: + if ((view = vacm_get_view(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if ((view = vacm_get_next_view(&val->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + vacm_append_viewindex(&val->var, sub, view); + break; + + case SNMP_OP_SET: + if ((view = vacm_get_view(&val->var, sub)) == NULL && + val->var.subs[sub - 1] != LEAF_vacmViewTreeFamilyStatus) + return (SNMP_ERR_NOSUCHNAME); + + if (view != NULL) { + if (community != COMM_INITIALIZE && + view->type == StorageType_readOnly) + return (SNMP_ERR_NOT_WRITEABLE); + if (view->status == RowStatus_active && + val->v.integer != RowStatus_destroy) + return (SNMP_ERR_INCONS_VALUE); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_vacmViewTreeFamilyMask: + if (val->v.octetstring.len > sizeof(view->mask)) + ctx->scratch->ptr1 = malloc(sizeof(view->mask)); + if (ctx->scratch->ptr1 == NULL) + return (SNMP_ERR_GENERR); + memset(ctx->scratch->ptr1, 0, sizeof(view->mask)); + memcpy(ctx->scratch->ptr1, view->mask, + sizeof(view->mask)); + memset(view->mask, 0, sizeof(view->mask)); + memcpy(view->mask, val->v.octetstring.octets, + val->v.octetstring.len); + break; + + case LEAF_vacmViewTreeFamilyType: + ctx->scratch->int1 = view->exclude; + if (val->v.integer == vacmViewTreeFamilyType_included) + view->exclude = 0; + else if (val->v.integer == vacmViewTreeFamilyType_excluded) + view->exclude = 1; + else + return (SNMP_ERR_WRONG_VALUE); + break; + + case LEAF_vacmViewTreeFamilyStorageType: + return (SNMP_ERR_INCONS_VALUE); + + case LEAF_vacmViewTreeFamilyStatus: + if (view == NULL) { + if (val->v.integer != RowStatus_createAndGo || + vacm_view_index_decode(&val->var, sub, vname, + &oid) < 0) + return (SNMP_ERR_INCONS_VALUE); + if ((view = vacm_new_view(vname, &oid)) == NULL) + return (SNMP_ERR_GENERR); + view->status = RowStatus_destroy; + if (community != COMM_INITIALIZE) + view->type = StorageType_volatile; + else + view->type = StorageType_readOnly; + } else if (val->v.integer != RowStatus_active && + val->v.integer != RowStatus_destroy) + return (SNMP_ERR_INCONS_VALUE); + ctx->scratch->int1 = view->status; + view->status = val->v.integer; + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + switch (val->var.subs[sub - 1]) { + case LEAF_vacmViewTreeFamilyMask: + free(ctx->scratch->ptr1); + break; + case LEAF_vacmViewTreeFamilyStatus: + if ((view = vacm_get_view(&val->var, sub)) == NULL) + return (SNMP_ERR_GENERR); + switch (val->v.integer) { + case RowStatus_destroy: + return (vacm_delete_view(view)); + + case RowStatus_createAndGo: + view->status = RowStatus_active; + break; + + default: + /* NOTREACHED*/ + return (SNMP_ERR_GENERR); + } + default: + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + if ((view = vacm_get_view(&val->var, sub)) == NULL) + return (SNMP_ERR_GENERR); + switch (val->var.subs[sub - 1]) { + case LEAF_vacmViewTreeFamilyMask: + memcpy(view->mask, ctx->scratch->ptr1, + sizeof(view->mask)); + free(ctx->scratch->ptr1); + break; + case LEAF_vacmViewTreeFamilyType: + view->exclude = ctx->scratch->int1; + break; + case LEAF_vacmViewTreeFamilyStatus: + if (ctx->scratch->int1 == RowStatus_destroy) + return (vacm_delete_view(view)); + break; + default: + break; + } + return (SNMP_ERR_NOERROR); + + default: + abort(); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_vacmViewTreeFamilyMask: + return (string_get(val, view->mask, sizeof(view->mask))); + case LEAF_vacmViewTreeFamilyType: + if (view->exclude) + val->v.integer = vacmViewTreeFamilyType_excluded; + else + val->v.integer = vacmViewTreeFamilyType_included; + break; + case LEAF_vacmViewTreeFamilyStorageType: + val->v.integer = view->type; + break; + case LEAF_vacmViewTreeFamilyStatus: + val->v.integer = view->status; + break; + default: + abort(); + } + + return (SNMP_ERR_NOERROR); +} + +static void +vacm_append_userindex(struct asn_oid *oid, uint sub, + const struct vacm_user *user) +{ + uint32_t i; + + oid->len = sub + strlen(user->secname) + 2; + oid->subs[sub++] = user->sec_model; + oid->subs[sub] = strlen(user->secname); + for (i = 1; i <= strlen(user->secname); i++) + oid->subs[sub + i] = user->secname[i - 1]; +} + +static int +vacm_user_index_decode(const struct asn_oid *oid, uint sub, + int32_t *smodel, char *uname) +{ + uint32_t i; + + *smodel = oid->subs[sub++]; + + if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ) + return (-1); + + for (i = 0; i < oid->subs[sub]; i++) + uname[i] = oid->subs[sub + i + 1]; + uname[i] = '\0'; + + return (0); +} + +static struct vacm_user * +vacm_get_user(const struct asn_oid *oid, uint sub) +{ + int32_t smodel; + char uname[SNMP_ADM_STR32_SIZ]; + struct vacm_user *user; + + if (vacm_user_index_decode(oid, sub, &smodel, uname) < 0) + return (NULL); + + for (user = vacm_first_user(); user != NULL; user = vacm_next_user(user)) + if (strcmp(uname, user->secname) == 0 && + user->sec_model == smodel) + return (user); + + return (NULL); +} + +static struct vacm_user * +vacm_get_next_user(const struct asn_oid *oid, uint sub) +{ + int32_t smodel; + char uname[SNMP_ADM_STR32_SIZ]; + struct vacm_user *user; + + if (oid->len - sub == 0) + return (vacm_first_user()); + + if (vacm_user_index_decode(oid, sub, &smodel, uname) < 0) + return (NULL); + + for (user = vacm_first_user(); user != NULL; user = vacm_next_user(user)) + if (strcmp(uname, user->secname) == 0 && + user->sec_model == smodel) + return (vacm_next_user(user)); + + return (NULL); +} + +static void +vacm_append_access_rule_index(struct asn_oid *oid, uint sub, + const struct vacm_access *acl) +{ + uint32_t i; + + oid->len = sub + strlen(acl->group->groupname) + + strlen(acl->ctx_prefix) + 4; + + oid->subs[sub] = strlen(acl->group->groupname); + for (i = 1; i <= strlen(acl->group->groupname); i++) + oid->subs[sub + i] = acl->group->groupname[i - 1]; + sub += strlen(acl->group->groupname) + 1; + + oid->subs[sub] = strlen(acl->ctx_prefix); + for (i = 1; i <= strlen(acl->ctx_prefix); i++) + oid->subs[sub + i] = acl->ctx_prefix[i - 1]; + sub += strlen(acl->ctx_prefix) + 1; + oid->subs[sub++] = acl->sec_model; + oid->subs[sub] = acl->sec_level; +} + +static int +vacm_access_rule_index_decode(const struct asn_oid *oid, uint sub, char *gname, + char *cprefix, int32_t *smodel, int32_t *slevel) +{ + uint32_t i; + + if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ) + return (-1); + + for (i = 0; i < oid->subs[sub]; i++) + gname[i] = oid->subs[sub + i + 1]; + gname[i] = '\0'; + sub += strlen(gname) + 1; + + if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ) + return (-1); + + for (i = 0; i < oid->subs[sub]; i++) + cprefix[i] = oid->subs[sub + i + 1]; + cprefix[i] = '\0'; + sub += strlen(cprefix) + 1; + + *smodel = oid->subs[sub++]; + *slevel = oid->subs[sub]; + + return (0); +} + +struct vacm_access * +vacm_get_access_rule(const struct asn_oid *oid, uint sub) +{ + int32_t smodel, slevel; + char gname[SNMP_ADM_STR32_SIZ], prefix[SNMP_ADM_STR32_SIZ]; + struct vacm_access *acl; + + if (vacm_access_rule_index_decode(oid, sub, gname, prefix, &smodel, + &slevel) < 0) + return (NULL); + + for (acl = vacm_first_access_rule(); acl != NULL; + acl = vacm_next_access_rule(acl)) + if (strcmp(gname, acl->group->groupname) == 0 && + strcmp(prefix, acl->ctx_prefix) == 0 && + smodel == acl->sec_model && slevel == acl->sec_level) + return (acl); + + return (NULL); +} + +struct vacm_access * +vacm_get_next_access_rule(const struct asn_oid *oid __unused, uint sub __unused) +{ + int32_t smodel, slevel; + char gname[SNMP_ADM_STR32_SIZ], prefix[SNMP_ADM_STR32_SIZ]; + struct vacm_access *acl; + + if (oid->len - sub == 0) + return (vacm_first_access_rule()); + + if (vacm_access_rule_index_decode(oid, sub, gname, prefix, &smodel, + &slevel) < 0) + return (NULL); + + for (acl = vacm_first_access_rule(); acl != NULL; + acl = vacm_next_access_rule(acl)) + if (strcmp(gname, acl->group->groupname) == 0 && + strcmp(prefix, acl->ctx_prefix) == 0 && + smodel == acl->sec_model && slevel == acl->sec_model) + return (vacm_next_access_rule(acl)); + + return (NULL); +} + +static int +vacm_view_index_decode(const struct asn_oid *oid, uint sub, char *vname, + struct asn_oid *view_oid) +{ + uint32_t i; + int viod_off; + + if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ) + return (-1); + + for (i = 0; i < oid->subs[sub]; i++) + vname[i] = oid->subs[sub + i + 1]; + vname[i] = '\0'; + + viod_off = sub + oid->subs[sub] + 1; + if ((view_oid->len = oid->subs[viod_off]) > ASN_MAXOIDLEN) + return (-1); + + memcpy(&view_oid->subs[0], &oid->subs[viod_off + 1], + view_oid->len * sizeof(view_oid->subs[0])); + + return (0); +} + +static void +vacm_append_viewindex(struct asn_oid *oid, uint sub, const struct vacm_view *view) +{ + uint32_t i; + + oid->len = sub + strlen(view->viewname) + 1; + oid->subs[sub] = strlen(view->viewname); + for (i = 1; i <= strlen(view->viewname); i++) + oid->subs[sub + i] = view->viewname[i - 1]; + + sub += strlen(view->viewname) + 1; + oid->subs[sub] = view->subtree.len; + oid->len++; + asn_append_oid(oid, &view->subtree); +} + +struct vacm_view * +vacm_get_view(const struct asn_oid *oid, uint sub) +{ + char vname[SNMP_ADM_STR32_SIZ]; + struct asn_oid subtree; + struct vacm_view *view; + + if (vacm_view_index_decode(oid, sub, vname, &subtree) < 0) + return (NULL); + + for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view)) + if (strcmp(vname, view->viewname) == 0 && + asn_compare_oid(&subtree, &view->subtree)== 0) + return (view); + + return (NULL); +} + +struct vacm_view * +vacm_get_next_view(const struct asn_oid *oid, uint sub) +{ + char vname[SNMP_ADM_STR32_SIZ]; + struct asn_oid subtree; + struct vacm_view *view; + + if (oid->len - sub == 0) + return (vacm_first_view()); + + if (vacm_view_index_decode(oid, sub, vname, &subtree) < 0) + return (NULL); + + for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view)) + if (strcmp(vname, view->viewname) == 0 && + asn_compare_oid(&subtree, &view->subtree)== 0) + return (vacm_next_view(view)); + + return (NULL); +} + +static struct vacm_view * +vacm_get_view_by_name(u_char *octets, u_int len) +{ + struct vacm_view *view; + + for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view)) + if (strlen(view->viewname) == len && + memcmp(octets, view->viewname, len) == 0) + return (view); + + return (NULL); +} + +static struct vacm_context * +vacm_get_context(const struct asn_oid *oid, uint sub) +{ + char cname[SNMP_ADM_STR32_SIZ]; + size_t cnamelen; + u_int index_count; + struct vacm_context *vacm_ctx; + + if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ) + return (NULL); + + index_count = 0; + index_count = SNMP_INDEX(index_count, 1); + if (index_decode(oid, sub, index_count, &cname, &cnamelen)) + return (NULL); + + for (vacm_ctx = vacm_first_context(); vacm_ctx != NULL; + vacm_ctx = vacm_next_context(vacm_ctx)) + if (strcmp(cname, vacm_ctx->ctxname) == 0) + return (vacm_ctx); + + return (NULL); +} + +static struct vacm_context * +vacm_get_next_context(const struct asn_oid *oid, uint sub) +{ + char cname[SNMP_ADM_STR32_SIZ]; + size_t cnamelen; + u_int index_count; + struct vacm_context *vacm_ctx; + + if (oid->len - sub == 0) + return (vacm_first_context()); + + if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ) + return (NULL); + + index_count = 0; + index_count = SNMP_INDEX(index_count, 1); + if (index_decode(oid, sub, index_count, &cname, &cnamelen)) + return (NULL); + + for (vacm_ctx = vacm_first_context(); vacm_ctx != NULL; + vacm_ctx = vacm_next_context(vacm_ctx)) + if (strcmp(cname, vacm_ctx->ctxname) == 0) + return (vacm_next_context(vacm_ctx)); + + return (NULL); +} + +static void +vacm_append_ctxindex(struct asn_oid *oid, uint sub, + const struct vacm_context *ctx) +{ + uint32_t i; + + oid->len = sub + strlen(ctx->ctxname) + 1; + oid->subs[sub] = strlen(ctx->ctxname); + for (i = 1; i <= strlen(ctx->ctxname); i++) + oid->subs[sub + i] = ctx->ctxname[i - 1]; +} + +/* + * VACM snmp module initialization hook. + * Returns 0 on success, < 0 on error. + */ +static int +vacm_init(struct lmodule *mod, int argc __unused, char *argv[] __unused) +{ + vacm_module = mod; + vacm_lock = random(); + vacm_groups_init(); + + /* XXX: TODO - initialize structures */ + return (0); +} + +/* + * VACM snmp module finalization hook. + */ +static int +vacm_fini(void) +{ + /* XXX: TODO - cleanup */ + vacm_flush_contexts(reg_vacm); + or_unregister(reg_vacm); + + return (0); +} + +/* + * VACM snmp module start operation. + */ +static void +vacm_start(void) +{ + static char dflt_ctx[] = ""; + + reg_vacm = or_register(&oid_vacm, + "The MIB module for managing SNMP View-based Access Control Model.", + vacm_module); + + (void)vacm_add_context(dflt_ctx, reg_vacm); +} + +static void +vacm_dump(void) +{ + struct vacm_context *vacmctx; + struct vacm_user *vuser; + struct vacm_access *vacl; + struct vacm_view *view; + static char oidbuf[ASN_OIDSTRLEN]; + + syslog(LOG_ERR, "\n"); + syslog(LOG_ERR, "Context list:"); + for (vacmctx = vacm_first_context(); vacmctx != NULL; + vacmctx = vacm_next_context(vacmctx)) + syslog(LOG_ERR, "Context \"%s\", module id %d", + vacmctx->ctxname, vacmctx->regid); + + syslog(LOG_ERR, "VACM users:"); + for (vuser = vacm_first_user(); vuser != NULL; + vuser = vacm_next_user(vuser)) + syslog(LOG_ERR, "Uname %s, Group %s, model %d", vuser->secname, + vuser->group!= NULL?vuser->group->groupname:"Unknown", + vuser->sec_model); + + syslog(LOG_ERR, "VACM Access rules:"); + for (vacl = vacm_first_access_rule(); vacl != NULL; + vacl = vacm_next_access_rule(vacl)) + syslog(LOG_ERR, "Group %s, CtxPrefix %s, Model %d, Level %d, " + "RV %s, WR %s, NV %s", vacl->group!=NULL? + vacl->group->groupname:"Unknown", vacl->ctx_prefix, + vacl->sec_model, vacl->sec_level, vacl->read_view!=NULL? + vacl->read_view->viewname:"None", vacl->write_view!=NULL? + vacl->write_view->viewname:"None", vacl->notify_view!=NULL? + vacl->notify_view->viewname:"None"); + + syslog(LOG_ERR, "VACM Views:"); + for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view)) + syslog(LOG_ERR, "View %s, Tree %s - %s", view->viewname, + asn_oid2str_r(&view->subtree, oidbuf), view->exclude? + "excluded":"included"); +} + +const char vacm_comment[] = \ +"This module implements SNMP View-based Access Control Model defined in RFC 3415."; + +const struct snmp_module config = { + .comment = vacm_comment, + .init = vacm_init, + .fini = vacm_fini, + .start = vacm_start, + .tree = vacm_ctree, + .dump = vacm_dump, + .tree_size = vacm_CTREE_SIZE, +}; Property changes on: vendor/bsnmp/1.13/snmp_vacm/vacm_snmp.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmp_vacm/vacm_tree.def =================================================================== --- vendor/bsnmp/1.13/snmp_vacm/vacm_tree.def (nonexistent) +++ vendor/bsnmp/1.13/snmp_vacm/vacm_tree.def (revision 336778) @@ -0,0 +1,89 @@ +#- +# Copyright (C) 2010 The FreeBSD Foundation +# All rights reserved. +# +# This software was developed by Shteryana Sotirova Shopova under +# sponsorship from the FreeBSD Foundation. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +include "tc.def" + +(1 internet + (6 snmpV2 + (3 snmpModules + (16 snmpVacmMIB + (1 vacmMIBObjects + (1 vacmContextTable + (1 vacmContextEntry : OCTETSTRING op_vacm_context + (1 vacmContextName OCTETSTRING GET) + ) + ) + (2 vacmSecurityToGroupTable + (1 vacmSecurityToGroupEntry : INTEGER OCTETSTRING op_vacm_security_to_group + (1 vacmSecurityModel INTEGER) + (2 vacmSecurityName OCTETSTRING) + (3 vacmGroupName OCTETSTRING GET SET) + (4 vacmSecurityToGroupStorageType StorageType GET SET) + (5 vacmSecurityToGroupStatus RowStatus GET SET) + ) + ) + (4 vacmAccessTable + (1 vacmAccessEntry : OCTETSTRING OCTETSTRING INTEGER ENUM ( 1 noAuthNoPriv 2 authNoPriv 3 authPriv ) op_vacm_access + (1 vacmAccessContextPrefix OCTETSTRING) + (2 vacmAccessSecurityModel INTEGER) + (3 vacmAccessSecurityLevel ENUM ( 1 noAuthNoPriv 2 authNoPriv 3 authPriv )) + (4 vacmAccessContextMatch ENUM ( 1 exact 2 prefix ) GET SET) + (5 vacmAccessReadViewName OCTETSTRING GET SET) + (6 vacmAccessWriteViewName OCTETSTRING GET SET) + (7 vacmAccessNotifyViewName OCTETSTRING GET SET) + (8 vacmAccessStorageType StorageType GET SET) + (9 vacmAccessStatus RowStatus GET SET) + ) + ) + (5 vacmMIBViews + (1 vacmViewSpinLock INTEGER op_vacm_view_lock GET SET) + (2 vacmViewTreeFamilyTable + (1 vacmViewTreeFamilyEntry : OCTETSTRING OID op_vacm_view + (1 vacmViewTreeFamilyViewName OCTETSTRING) + (2 vacmViewTreeFamilySubtree OID) + (3 vacmViewTreeFamilyMask OCTETSTRING GET SET) + (4 vacmViewTreeFamilyType ENUM ( 1 included 2 excluded ) GET SET) + (5 vacmViewTreeFamilyStorageType StorageType GET SET) + (6 vacmViewTreeFamilyStatus RowStatus GET SET) + ) + ) + ) + ) + (2 vacmMIBConformance + (1 vacmMIBCompliances + ) + (2 vacmMIBGroups + ) + ) + ) + ) + ) +) Property changes on: vendor/bsnmp/1.13/snmp_vacm/vacm_tree.def ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/BEGEMOT-MIB.txt =================================================================== --- vendor/bsnmp/1.13/snmpd/BEGEMOT-MIB.txt (nonexistent) +++ vendor/bsnmp/1.13/snmpd/BEGEMOT-MIB.txt (revision 336778) @@ -0,0 +1,62 @@ +-- +-- Copyright (c) 2001-2003 +-- Fraunhofer Institute for Open Communication Systems (FhG Fokus). +-- All rights reserved. +-- +-- Author: Harti Brandt +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- 1. Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- 2. Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +-- ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +-- SUCH DAMAGE. +-- +-- $Begemot: bsnmp/snmpd/BEGEMOT-MIB.txt,v 1.5 2004/08/06 08:47:07 brandt Exp $ +-- +-- Begemot private definitions and root. +-- +BEGEMOT-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY + FROM SNMPv2-SMI + fokus + FROM FOKUS-MIB; + +begemot MODULE-IDENTITY + LAST-UPDATED "200201300000Z" + ORGANIZATION "Fraunhofer FOKUS, CATS" + CONTACT-INFO + " Hartmut Brandt + + Postal: Fraunhofer Institute for Open Communication Systems + Kaiserin-Augusta-Allee 31 + 10589 Berlin + Germany + + Fax: +49 30 3463 7352 + + E-mail: harti@freebsd.org" + DESCRIPTION + "The root of the Begemot subtree of the fokus tree." + REVISION "200201300000Z" + DESCRIPTION + "Initial revision." + ::= { fokus 1 } + +END Property changes on: vendor/bsnmp/1.13/snmpd/BEGEMOT-MIB.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/BEGEMOT-SNMPD.txt =================================================================== --- vendor/bsnmp/1.13/snmpd/BEGEMOT-SNMPD.txt (nonexistent) +++ vendor/bsnmp/1.13/snmpd/BEGEMOT-SNMPD.txt (revision 336778) @@ -0,0 +1,579 @@ +-- +-- Copyright (c) 2001-2003 +-- Fraunhofer Institute for Open Communication Systems (FhG Fokus). +-- All rights reserved. +-- +-- Author: Harti Brandt +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- 1. Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- 2. Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +-- ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +-- SUCH DAMAGE. +-- +-- $Begemot: bsnmp/snmpd/BEGEMOT-SNMPD.txt,v 1.23 2004/08/06 08:47:08 brandt Exp $ +-- +-- Begemot Private SNMPd MIB. +-- +BEGEMOT-SNMPD-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, OBJECT-IDENTITY, Counter32, + Unsigned32, IpAddress + FROM SNMPv2-SMI + TEXTUAL-CONVENTION, TruthValue, RowStatus + FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP + FROM SNMPv2-CONF + begemot + FROM BEGEMOT-MIB; + +begemotSnmpd MODULE-IDENTITY + LAST-UPDATED "201801190000Z" + ORGANIZATION "Fraunhofer FOKUS, CATS" + CONTACT-INFO + " Hartmut Brandt + + Postal: Fraunhofer Institute for Open Communication Systems + Kaiserin-Augusta-Allee 31 + 10589 Berlin + Germany + + Fax: +49 30 3463 7352 + + E-mail: harti@freebsd.org" + DESCRIPTION + "The MIB module for the Begemot SNMP daemon." + ::= { begemot 1 } + +begemotSnmpdObjects OBJECT IDENTIFIER ::= { begemotSnmpd 1 } +begemotSnmpdDefs OBJECT IDENTIFIER ::= { begemotSnmpd 2 } + +-- -------------------------------------------------------------------------- + +SectionName ::= TEXTUAL-CONVENTION + DISPLAY-HINT "14a" + STATUS current + DESCRIPTION + "Name of a loadable module. Should consist of alphanumeric characers + only, the first character must be a letter." + SYNTAX OCTET STRING (SIZE(1..14)) + +-- -------------------------------------------------------------------------- +-- +-- Agent types +-- +begemotSnmpdAgent OBJECT IDENTIFIER ::= { begemotSnmpdDefs 1 } + +begemotSnmpdAgentFreeBSD OBJECT-IDENTITY + STATUS current + DESCRIPTION + "Identifies the agent as running on FreeBSD." + ::= { begemotSnmpdAgent 1 } + +-- -------------------------------------------------------------------------- +-- +-- The Config Group +-- +begemotSnmpdConfig OBJECT IDENTIFIER ::= { begemotSnmpdObjects 1 } + +begemotSnmpdTransmitBuffer OBJECT-TYPE + SYNTAX INTEGER (484..65535) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The size of the receive buffer in bytes. Larger messages + are dropped by SNMPd." + DEFVAL { 2048 } + ::= { begemotSnmpdConfig 1 } + +begemotSnmpdReceiveBuffer OBJECT-TYPE + SYNTAX INTEGER (484..65535) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The size of the transmit buffer in bytes. Larger messages + cannot be sent by the SNMPd." + DEFVAL { 2048 } + ::= { begemotSnmpdConfig 2 } + +begemotSnmpdCommunityDisable OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Disables all access to the CommunityTable from SNMP. Once + set it cannot be cleared." + DEFVAL { false } + ::= { begemotSnmpdConfig 3 } + +begemotSnmpdTrap1Addr OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The trap sink for v1 traps." + ::= { begemotSnmpdConfig 4 } + +begemotSnmpdVersionEnable OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The SNMP versions that the agent processes. The following + bits are defined: + + 0x00000001 - SNMPv1 + 0x00000002 - SNMPv2c + 0x00000004 - SNMPv3" + DEFVAL { 3 } + ::= { begemotSnmpdConfig 5 } + +-- +-- Trap destinations +-- +begemotTrapSinkTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotTrapSinkEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table with destinations for standard traps." + INDEX { begemotTrapSinkAddr, begemotTrapSinkPort } + ::= { begemotSnmpdObjects 2 } + +begemotTrapSinkEntry OBJECT-TYPE + SYNTAX BegemotTrapSinkEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Entry describes one trap destination." + INDEX { begemotTrapSinkAddr, begemotTrapSinkPort } + ::= { begemotTrapSinkTable 1 } + +BegemotTrapSinkEntry ::= SEQUENCE { + begemotTrapSinkAddr IpAddress, + begemotTrapSinkPort INTEGER, + begemotTrapSinkStatus RowStatus +} + +begemotTrapSinkAddr OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Destination IP address of the manager station where to send + traps." + ::= { begemotTrapSinkEntry 1 } + +begemotTrapSinkPort OBJECT-TYPE + SYNTAX INTEGER (1..65535) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Destination UDP port of the manager station where to send + traps." + ::= { begemotTrapSinkEntry 2 } + +begemotTrapSinkStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "Used to create/activate/destroy the entry." + ::= { begemotTrapSinkEntry 3 } + +-- +-- SNMP port table +-- +begemotSnmpdPortTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotSnmpdPortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table with descriptions of UDP ports to listen on + for SNMP messages." + ::= { begemotSnmpdObjects 4 } + +begemotSnmpdPortEntry OBJECT-TYPE + SYNTAX BegemotSnmpdPortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry in the table with descriptions of UDP ports to + listen on for SNMP messages." + INDEX { begemotSnmpdPortAddress, begemotSnmpdPortPort } + ::= { begemotSnmpdPortTable 1 } + +BegemotSnmpdPortEntry ::= SEQUENCE { + begemotSnmpdPortAddress IpAddress, + begemotSnmpdPortPort INTEGER, + begemotSnmpdPortStatus INTEGER +} + +begemotSnmpdPortAddress OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The IP address to bind to." + ::= { begemotSnmpdPortEntry 1 } + +begemotSnmpdPortPort OBJECT-TYPE + SYNTAX INTEGER (1..65535) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The UDP port to listen on for SNMP messages." + ::= { begemotSnmpdPortEntry 2 } + +begemotSnmpdPortStatus OBJECT-TYPE + SYNTAX INTEGER { valid(1), invalid(2) } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "Set status to 1 to create entry, set it to 2 to delete it." + ::= { begemotSnmpdPortEntry 3 } + +--- +--- Community table +--- +begemotSnmpdCommunityTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotSnmpdCommunityEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table with the community strings for access control." + ::= { begemotSnmpdObjects 5 } + +begemotSnmpdCommunityEntry OBJECT-TYPE + SYNTAX BegemotSnmpdCommunityEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table with the community strings for access control. + When begemotSnmpdCommDisable is true, this table disappears." + INDEX { begemotSnmpdCommunityModule, begemotSnmpdCommunityIndex } + ::= { begemotSnmpdCommunityTable 1 } + +BegemotSnmpdCommunityEntry ::= SEQUENCE { + begemotSnmpdCommunityModule SectionName, + begemotSnmpdCommunityIndex Unsigned32, + begemotSnmpdCommunityString OCTET STRING, + begemotSnmpdCommunityDescr OCTET STRING, + begemotSnmpdCommunityPermission INTEGER +} + +begemotSnmpdCommunityModule OBJECT-TYPE + SYNTAX SectionName + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Index of the module that has registered this community. + For global communities this is the empty string." + ::= { begemotSnmpdCommunityEntry 1 } + +begemotSnmpdCommunityIndex OBJECT-TYPE + SYNTAX Unsigned32 (1..4294967295) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The numerical index of the community (private to the module)." + ::= { begemotSnmpdCommunityEntry 2 } + +begemotSnmpdCommunityString OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The string for access to SNMPd." + ::= { begemotSnmpdCommunityEntry 3 } + +begemotSnmpdCommunityDescr OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A description what this community is good for." + ::= { begemotSnmpdCommunityEntry 4 } + +begemotSnmpdCommunityPermission OBJECT-TYPE + SYNTAX INTEGER (1..4294967295) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The numerical value of access rights granted to the community." + ::= { begemotSnmpdCommunityEntry 5 } + +-- +-- Module table +-- +begemotSnmpdModuleTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotSnmpdModuleEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table describing all the currently loaded dynamic modules. + Writing to this table loads and unloads modules." + ::= { begemotSnmpdObjects 6 } + +begemotSnmpdModuleEntry OBJECT-TYPE + SYNTAX BegemotSnmpdModuleEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table entry describing a loadable module." + INDEX { begemotSnmpdModuleSection } + ::= { begemotSnmpdModuleTable 1 } + +BegemotSnmpdModuleEntry ::= SEQUENCE { + begemotSnmpdModuleSection SectionName, + begemotSnmpdModulePath OCTET STRING, + begemotSnmpdModuleComment OCTET STRING +} + +begemotSnmpdModuleSection OBJECT-TYPE + SYNTAX SectionName + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The string used for matching configuration file sections + and indexes the module table." + ::= { begemotSnmpdModuleEntry 1 } + + +begemotSnmpdModulePath OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The path name of the module. Set to empty string + to unload a module. The path of an existing module + may not be changed." + ::= { begemotSnmpdModuleEntry 2 } + +begemotSnmpdModuleComment OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A comment describing this module." + ::= { begemotSnmpdModuleEntry 3 } + + +-- -------------------------------------------------------------------------- +-- +-- The STATISTICS Group +-- +begemotSnmpdStats OBJECT IDENTIFIER ::= { begemotSnmpdObjects 7 } + +begemotSnmpdStatsNoRxBufs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Number of times a receive buffer could not be allocated + for a packet." + ::= { begemotSnmpdStats 1 } + +begemotSnmpdStatsNoTxBufs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Number of times a transmit buffer could not be allocated + for a packet." + ::= { begemotSnmpdStats 2 } + +begemotSnmpdStatsInTooLongPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Number of packets received that were longer than the + receive buffer. These packets are dropped." + ::= { begemotSnmpdStats 3 } + +begemotSnmpdStatsInBadPduTypes OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Number of packets received with a bad type field." + ::= { begemotSnmpdStats 4 } + +-- +-- The Debug Group +-- +begemotSnmpdDebug OBJECT IDENTIFIER ::= { begemotSnmpdObjects 8 } + +begemotSnmpdDebugDumpPdus OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Dump PDUs to log file if true." + DEFVAL { false } + ::= { begemotSnmpdDebug 1 } + +begemotSnmpdDebugSnmpTrace OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Tracing flags for the SNMP library. These flags have the + following meaning: + 0x00000001 trace GET operator + 0x00000002 trace GETNEXT operator + 0x00000004 trace SET operator + 0x00000008 trace dependency processing + 0x00000010 trace node finding + 0x10000000 log ASN1 errors + 0x20000000 log SNMP errors + Individual values can be or-ed together." + DEFVAL { 0 } + ::= { begemotSnmpdDebug 2 } + +begemotSnmpdDebugSyslogPri OBJECT-TYPE + SYNTAX INTEGER (0..8) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Events with this or higher priority should not be logged." + DEFVAL { 7 } -- don't log debug messages + ::= { begemotSnmpdDebug 3 } + +-- +-- Local port table +-- +begemotSnmpdLocalPortTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotSnmpdLocalPortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table with descriptions of local (unix domain) ports to listen + on for SNMP messages." + ::= { begemotSnmpdObjects 9 } + +begemotSnmpdLocalPortEntry OBJECT-TYPE + SYNTAX BegemotSnmpdLocalPortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry in the table with descriptions of local ports to + listen on for SNMP messages." + INDEX { begemotSnmpdLocalPortPath } + ::= { begemotSnmpdLocalPortTable 1 } + +BegemotSnmpdLocalPortEntry ::= SEQUENCE { + begemotSnmpdLocalPortPath OCTET STRING, + begemotSnmpdLocalPortStatus INTEGER, + begemotSnmpdLocalPortType INTEGER +} + +begemotSnmpdLocalPortPath OBJECT-TYPE + SYNTAX OCTET STRING (SIZE(1..104)) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The path name to create and listen on." + ::= { begemotSnmpdLocalPortEntry 1 } + +begemotSnmpdLocalPortStatus OBJECT-TYPE + SYNTAX INTEGER { valid(1), invalid(2) } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "Set status to 1 to create entry, set it to 2 to delete it." + ::= { begemotSnmpdLocalPortEntry 2 } + +begemotSnmpdLocalPortType OBJECT-TYPE + SYNTAX INTEGER { + dgram-unpriv(1), + dgram-priv(2), + stream-unpriv(3), + stream-priv(4) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "Type of the port. If the type is unpriv SET operations + are allowed from all clients if the community matches. For + priv SET operations are allowed only from peers with uid + zero. If the daemon cannot determine the peer uid it disallows + the SET operation for -priv ports." + ::= { begemotSnmpdLocalPortEntry 3 } + +-- +-- Transport mapping table +-- +begemotSnmpdTransportMappings OBJECT IDENTIFIER ::= { begemotSnmpdObjects 10 } + +begemotSnmpdTransportTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotSnmpdTransportEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table containing all the currently loaded transport mappings." + ::= { begemotSnmpdTransportMappings 1 } + +begemotSnmpdTransportEntry OBJECT-TYPE + SYNTAX BegemotSnmpdTransportEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry in the table with the transport mappings." + INDEX { begemotSnmpdTransportName } + ::= { begemotSnmpdTransportTable 1 } + +BegemotSnmpdTransportEntry ::= SEQUENCE { + begemotSnmpdTransportName OCTET STRING, + begemotSnmpdTransportStatus INTEGER, + begemotSnmpdTransportOid OBJECT IDENTIFIER +} + +begemotSnmpdTransportName OBJECT-TYPE + SYNTAX OCTET STRING (SIZE(1..256)) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The name of the mapping." + ::= { begemotSnmpdTransportEntry 1 } + +begemotSnmpdTransportStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Used to create/activate/destroy the entry." + ::= { begemotSnmpdTransportEntry 2 } + +begemotSnmpdTransportOid OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A pointer to the group with the transport-dependend stuff." + ::= { begemotSnmpdTransportEntry 3 } + +-- +-- XXX These should go into their own MIB +-- +begemotSnmpdTransUdp OBJECT IDENTIFIER ::= { begemotSnmpdTransportMappings 2 } +begemotSnmpdTransLsock OBJECT IDENTIFIER ::= { begemotSnmpdTransportMappings 3 } + +END Property changes on: vendor/bsnmp/1.13/snmpd/BEGEMOT-SNMPD.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/FOKUS-MIB.txt =================================================================== --- vendor/bsnmp/1.13/snmpd/FOKUS-MIB.txt (nonexistent) +++ vendor/bsnmp/1.13/snmpd/FOKUS-MIB.txt (revision 336778) @@ -0,0 +1,60 @@ +-- +-- Copyright (c) 2001-2003 +-- Fraunhofer Institute for Open Communication Systems (FhG Fokus). +-- All rights reserved. +-- +-- Author: Harti Brandt +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- 1. Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- 2. Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +-- ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +-- SUCH DAMAGE. +-- +-- $Begemot: bsnmp/snmpd/FOKUS-MIB.txt,v 1.5 2004/08/06 08:47:08 brandt Exp $ +-- +-- Begemot private definitions and fokus root. +-- +FOKUS-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, enterprises + FROM SNMPv2-SMI; + +fokus MODULE-IDENTITY + LAST-UPDATED "200202050000Z" + ORGANIZATION "Fraunhofer FOKUS, CATS" + CONTACT-INFO + " Hartmut Brandt + + Postal: Fraunhofer Institute for Open Communication Systems + Kaiserin-Augusta-Allee 31 + 10589 Berlin + Germany + + Fax: +49 30 3463 7352 + + E-mail: harti@freebsd.org" + DESCRIPTION + "The root of the Fokus enterprises tree." + REVISION "200202050000Z" + DESCRIPTION + "Initial revision." + ::= { enterprises 12325 } + +END Property changes on: vendor/bsnmp/1.13/snmpd/FOKUS-MIB.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/Makefile.in =================================================================== --- vendor/bsnmp/1.13/snmpd/Makefile.in (nonexistent) +++ vendor/bsnmp/1.13/snmpd/Makefile.in (revision 336778) @@ -0,0 +1,45 @@ +# Copyright (c) 2001-2003 +# Fraunhofer Institute for Open Communication Systems (FhG Fokus). +# All rights reserved. +# +# Author: Harti Brandt +# +# $Begemot: bsnmp/trunk/snmpd/Makefile.in 2117 2015-09-16 14:09:31Z brandt_h $ +# + +PROG= bsnmpd +SRCS= tree.c main.c action.c config.c export.c trap.c +SRCS+= trans_udp.c trans_lsock.c +MAN1= bsnmpd.1 +MAN3= snmpmod.3 +MANFILTER= sed -e 's%@MODPATH@%${LIBDIR}/%g' \ + -e 's%@DEFPATH@%${DEFSDIR}/%g' \ + -e 's%@MIBSPATH@%${MIBSDIR}/%g' + +XSYM= snmpMIB begemotSnmpdModuleTable begemotSnmpd begemotTrapSinkTable \ + sysUpTime snmpTrapOID coldStart authenticationFailure \ + begemotSnmpdLocalPortTable begemotSnmpdTransUdp begemotSnmpdTransLsock \ + freeBSDVersion freeBSD + +BMIBS= FOKUS-MIB.txt BEGEMOT-MIB.txt BEGEMOT-SNMPD.txt +DEFS= tree.def +INCS= snmpmod.h + +CFLAGS+= -I$(builddir)/. -I${srcdir} -I${srcdir}/../lib +LDFLAGS+= $(LIBDL) -export-dynamic + +$(PROG): $(SRCS:.c=.lo) oid.h tree.h + $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ $(SRCS:.c=.lo) \ + $(builddir)/../lib/libbsnmp.la $(LIBEV) $(LIBWRAP) + +CLEANFILES += tree.c tree.h oid.h *.3out *.1out + +GENSNMPTREE= $(builddir)/../gensnmptree/gensnmptree -I${srcdir}/../lib + +tree.c tree.h: tree.def ../gensnmptree/gensnmptree + ${GENSNMPTREE} -l <${srcdir}/tree.def + +oid.h: tree.def ../gensnmptree/gensnmptree + ${GENSNMPTREE} <${srcdir}/tree.def -e ${XSYM} >$@ + +$(SRCS:.c=.lo): oid.h Property changes on: vendor/bsnmp/1.13/snmpd/Makefile.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/action.c =================================================================== --- vendor/bsnmp/1.13/snmpd/action.c (nonexistent) +++ vendor/bsnmp/1.13/snmpd/action.c (revision 336778) @@ -0,0 +1,1270 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * Copyright (c) 2004-2006 + * Hartmut Brandt. + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: action.c 517 2006-10-31 08:52:04Z brandt_h $ + * + * Variable access for SNMPd + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "snmpmod.h" +#include "snmpd.h" +#include "tree.h" +#include "oid.h" + +static const struct asn_oid + oid_begemotSnmpdModuleTable = OIDX_begemotSnmpdModuleTable; + +#ifdef __FreeBSD__ +static const struct asn_oid + oid_freeBSDVersion = OIDX_freeBSDVersion; +#endif + +/* + * Get an integer value from the KERN sysctl subtree. + */ +static char * +act_getkernint(int id) +{ + int mib[2]; + size_t len; + u_long value; + char *string; + + mib[0] = CTL_KERN; + mib[1] = id; + len = sizeof(value); + if (sysctl(mib, 2, &value, &len, NULL, 0) != 0) + return (NULL); + + if ((string = malloc(20)) == NULL) + return (NULL); + sprintf(string, "%lu", value); + return (string); +} + +/* + * Initialize global variables of the system group. + */ +int +init_actvals(void) +{ + struct utsname uts; + char *hostid; + size_t len; +#ifdef __FreeBSD__ + char *rel, *p, *end; + u_long num; +#endif + + if (uname(&uts) == -1) + return (-1); + + if ((systemg.name = strdup(uts.nodename)) == NULL) + return (-1); + + if ((hostid = act_getkernint(KERN_HOSTID)) == NULL) + return (-1); + + len = strlen(uts.nodename) + 1; + len += strlen(hostid) + 1; + len += strlen(uts.sysname) + 1; + len += strlen(uts.release) + 1; + + if ((systemg.descr = malloc(len)) == NULL) { + free(hostid); + return (-1); + } + sprintf(systemg.descr, "%s %s %s %s", uts.nodename, hostid, uts.sysname, + uts.release); + +#ifdef __FreeBSD__ + /* + * Construct a FreeBSD oid + */ + systemg.object_id = oid_freeBSDVersion; + rel = uts.release; + while ((p = strsep(&rel, ".")) != NULL && + systemg.object_id.len < ASN_MAXOIDLEN) { + systemg.object_id.subs[systemg.object_id.len] = 0; + if (*p != '\0') { + num = strtoul(p, &end, 10); + if (end == p) + break; + systemg.object_id.subs[systemg.object_id.len] = num; + } + systemg.object_id.len++; + } +#endif + + free(hostid); + + return (0); +} + +/* + * Initialize global variables of the snmpEngine group. + */ +int +init_snmpd_engine(void) +{ + char *hostid; + + snmpd_engine.engine_boots = 1; + snmpd_engine.engine_time = 1; + snmpd_engine.max_msg_size = 1500; /* XXX */ + + snmpd_engine.engine_id[0] = ((OID_freeBSD & 0xff000000) >> 24) | 0x80; + snmpd_engine.engine_id[1] = (OID_freeBSD & 0xff0000) >> 16; + snmpd_engine.engine_id[2] = (OID_freeBSD & 0xff00) >> 8; + snmpd_engine.engine_id[3] = OID_freeBSD & 0xff; + snmpd_engine.engine_id[4] = 128; + snmpd_engine.engine_len = 5; + + if ((hostid = act_getkernint(KERN_HOSTID)) == NULL) + return (-1); + + if (strlen(hostid) > SNMP_ENGINE_ID_SIZ - snmpd_engine.engine_len) { + memcpy(snmpd_engine.engine_id + snmpd_engine.engine_len, + hostid, SNMP_ENGINE_ID_SIZ - snmpd_engine.engine_len); + snmpd_engine.engine_len = SNMP_ENGINE_ID_SIZ; + } else { + memcpy(snmpd_engine.engine_id + snmpd_engine.engine_len, + hostid, strlen(hostid)); + snmpd_engine.engine_len += strlen(hostid); + } + + free(hostid); + + return (0); +} + +int +set_snmpd_engine(void) +{ + FILE *fp; + uint32_t i; + uint8_t *cptr, engine[2 * SNMP_ENGINE_ID_SIZ + 2]; + uint8_t myengine[2 * SNMP_ENGINE_ID_SIZ + 2]; + + if (engine_file[0] == '\0') + return (-1); + + cptr = myengine; + for (i = 0; i < snmpd_engine.engine_len; i++) + cptr += sprintf(cptr, "%.2x", snmpd_engine.engine_id[i]); + *cptr++ = '\n'; + *cptr++ = '\0'; + + if ((fp = fopen(engine_file, "r+")) != NULL) { + if (fgets(engine, sizeof(engine) - 1, fp) == NULL || + fscanf(fp, "%u", &snmpd_engine.engine_boots) <= 0) { + fclose(fp); + goto save_boots; + } + + fclose(fp); + if (strcmp(myengine, engine) != 0) + snmpd_engine.engine_boots = 1; + else + snmpd_engine.engine_boots++; + } else if (errno != ENOENT) + return (-1); + +save_boots: + if ((fp = fopen(engine_file, "w+")) == NULL) + return (-1); + fprintf(fp, "%s%u\n", myengine, snmpd_engine.engine_boots); + fclose(fp); + + return (0); +} + +void +update_snmpd_engine_time(void) +{ + uint64_t etime; + + etime = (get_ticks() - start_tick) / 100ULL; + if (etime < INT32_MAX) + snmpd_engine.engine_time = etime; + else { + start_tick = get_ticks(); + (void)set_snmpd_engine(); + snmpd_engine.engine_time = start_tick; + } +} + +/************************************************************* + * + * System group + */ +int +op_system_group(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + break; + + case SNMP_OP_SET: + switch (which) { + + case LEAF_sysDescr: + if (community != COMM_INITIALIZE) + return (SNMP_ERR_NOT_WRITEABLE); + return (string_save(value, ctx, -1, &systemg.descr)); + + case LEAF_sysObjectId: + if (community != COMM_INITIALIZE) + return (SNMP_ERR_NOT_WRITEABLE); + return (oid_save(value, ctx, &systemg.object_id)); + + case LEAF_sysContact: + return (string_save(value, ctx, -1, &systemg.contact)); + + case LEAF_sysName: + return (string_save(value, ctx, -1, &systemg.name)); + + case LEAF_sysLocation: + return (string_save(value, ctx, -1, &systemg.location)); + } + return (SNMP_ERR_NO_CREATION); + + case SNMP_OP_ROLLBACK: + switch (which) { + + case LEAF_sysDescr: + string_rollback(ctx, &systemg.descr); + return (SNMP_ERR_NOERROR); + case LEAF_sysObjectId: + oid_rollback(ctx, &systemg.object_id); + return (SNMP_ERR_NOERROR); + case LEAF_sysContact: + string_rollback(ctx, &systemg.contact); + return (SNMP_ERR_NOERROR); + case LEAF_sysName: + string_rollback(ctx, &systemg.name); + return (SNMP_ERR_NOERROR); + case LEAF_sysLocation: + string_rollback(ctx, &systemg.location); + return (SNMP_ERR_NOERROR); + } + abort(); + + case SNMP_OP_COMMIT: + switch (which) { + + case LEAF_sysDescr: + string_commit(ctx); + return (SNMP_ERR_NOERROR); + case LEAF_sysObjectId: + oid_commit(ctx); + return (SNMP_ERR_NOERROR); + case LEAF_sysContact: + string_commit(ctx); + return (SNMP_ERR_NOERROR); + case LEAF_sysName: + string_commit(ctx); + return (SNMP_ERR_NOERROR); + case LEAF_sysLocation: + string_commit(ctx); + return (SNMP_ERR_NOERROR); + } + abort(); + } + + /* + * Come here for GET. + */ + switch (which) { + + case LEAF_sysDescr: + return (string_get(value, systemg.descr, -1)); + case LEAF_sysObjectId: + return (oid_get(value, &systemg.object_id)); + case LEAF_sysUpTime: + value->v.uint32 = get_ticks() - start_tick; + break; + case LEAF_sysContact: + return (string_get(value, systemg.contact, -1)); + case LEAF_sysName: + return (string_get(value, systemg.name, -1)); + case LEAF_sysLocation: + return (string_get(value, systemg.location, -1)); + case LEAF_sysServices: + value->v.integer = systemg.services; + break; + case LEAF_sysORLastChange: + value->v.uint32 = systemg.or_last_change; + break; + } + return (SNMP_ERR_NOERROR); +} + +/************************************************************* + * + * Debug group + */ +int +op_debug(struct snmp_context *ctx, struct snmp_value *value, u_int sub, + u_int iidx __unused, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + switch (which) { + + case LEAF_begemotSnmpdDebugDumpPdus: + value->v.integer = TRUTH_MK(debug.dump_pdus); + break; + + case LEAF_begemotSnmpdDebugSnmpTrace: + value->v.uint32 = snmp_trace; + break; + + case LEAF_begemotSnmpdDebugSyslogPri: + value->v.integer = debug.logpri; + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_SET: + switch (which) { + + case LEAF_begemotSnmpdDebugDumpPdus: + if (!TRUTH_OK(value->v.integer)) + return (SNMP_ERR_WRONG_VALUE); + ctx->scratch->int1 = debug.dump_pdus; + debug.dump_pdus = TRUTH_GET(value->v.integer); + return (SNMP_ERR_NOERROR); + + case LEAF_begemotSnmpdDebugSnmpTrace: + ctx->scratch->int1 = snmp_trace; + snmp_trace = value->v.uint32; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotSnmpdDebugSyslogPri: + if (value->v.integer < 0 || value->v.integer > 8) + return (SNMP_ERR_WRONG_VALUE); + ctx->scratch->int1 = debug.logpri; + debug.logpri = (u_int)value->v.integer; + return (SNMP_ERR_NOERROR); + } + return (SNMP_ERR_NO_CREATION); + + case SNMP_OP_ROLLBACK: + switch (which) { + + case LEAF_begemotSnmpdDebugDumpPdus: + debug.dump_pdus = ctx->scratch->int1; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotSnmpdDebugSnmpTrace: + snmp_trace = ctx->scratch->int1; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotSnmpdDebugSyslogPri: + debug.logpri = ctx->scratch->int1; + return (SNMP_ERR_NOERROR); + } + abort(); + + case SNMP_OP_COMMIT: + switch (which) { + + case LEAF_begemotSnmpdDebugDumpPdus: + case LEAF_begemotSnmpdDebugSnmpTrace: + return (SNMP_ERR_NOERROR); + + case LEAF_begemotSnmpdDebugSyslogPri: + if (debug.logpri == 0) + setlogmask(0); + else + setlogmask(LOG_UPTO(debug.logpri - 1)); + return (SNMP_ERR_NOERROR); + } + abort(); + } + abort(); +} + +/************************************************************* + * + * OR Table + */ +int +op_or_table(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + struct objres *objres; + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((objres = NEXT_OBJECT_INT(&objres_list, &value->var, sub)) + == NULL) + return (SNMP_ERR_NOSUCHNAME); + value->var.subs[sub] = objres->index; + value->var.len = sub + 1; + break; + + case SNMP_OP_GET: + if ((objres = FIND_OBJECT_INT(&objres_list, &value->var, sub)) + == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if ((objres = FIND_OBJECT_INT(&objres_list, &value->var, sub)) + == NULL) + return (SNMP_ERR_NO_CREATION); + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + default: + abort(); + } + + /* + * Come here for GET, GETNEXT. + */ + switch (value->var.subs[sub - 1]) { + + case LEAF_sysORID: + value->v.oid = objres->oid; + break; + + case LEAF_sysORDescr: + return (string_get(value, objres->descr, -1)); + + case LEAF_sysORUpTime: + value->v.uint32 = objres->uptime; + break; + } + return (SNMP_ERR_NOERROR); +} + +/************************************************************* + * + * mib-2 snmp + */ +int +op_snmp(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + switch (value->var.subs[sub - 1]) { + + case LEAF_snmpInPkts: + value->v.uint32 = snmpd_stats.inPkts; + break; + + case LEAF_snmpInBadVersions: + value->v.uint32 = snmpd_stats.inBadVersions; + break; + + case LEAF_snmpInBadCommunityNames: + value->v.uint32 = snmpd_stats.inBadCommunityNames; + break; + + case LEAF_snmpInBadCommunityUses: + value->v.uint32 = snmpd_stats.inBadCommunityUses; + break; + + case LEAF_snmpInASNParseErrs: + value->v.uint32 = snmpd_stats.inASNParseErrs; + break; + + case LEAF_snmpEnableAuthenTraps: + value->v.integer = TRUTH_MK(snmpd.auth_traps); + break; + + case LEAF_snmpSilentDrops: + value->v.uint32 = snmpd_stats.silentDrops; + break; + + case LEAF_snmpProxyDrops: + value->v.uint32 = snmpd_stats.proxyDrops; + break; + + default: + return (SNMP_ERR_NOSUCHNAME); + + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_SET: + switch (value->var.subs[sub - 1]) { + case LEAF_snmpEnableAuthenTraps: + if (!TRUTH_OK(value->v.integer)) + return (SNMP_ERR_WRONG_VALUE); + ctx->scratch->int1 = value->v.integer; + snmpd.auth_traps = TRUTH_GET(value->v.integer); + return (SNMP_ERR_NOERROR); + } + abort(); + + case SNMP_OP_ROLLBACK: + switch (value->var.subs[sub - 1]) { + case LEAF_snmpEnableAuthenTraps: + snmpd.auth_traps = ctx->scratch->int1; + return (SNMP_ERR_NOERROR); + } + abort(); + + case SNMP_OP_COMMIT: + switch (value->var.subs[sub - 1]) { + case LEAF_snmpEnableAuthenTraps: + return (SNMP_ERR_NOERROR); + } + abort(); + } + abort(); +} + +/************************************************************* + * + * SNMPd statistics group + */ +int +op_snmpd_stats(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + switch (op) { + + case SNMP_OP_GET: + switch (value->var.subs[sub - 1]) { + + case LEAF_begemotSnmpdStatsNoRxBufs: + value->v.uint32 = snmpd_stats.noRxbuf; + break; + + case LEAF_begemotSnmpdStatsNoTxBufs: + value->v.uint32 = snmpd_stats.noTxbuf; + break; + + case LEAF_begemotSnmpdStatsInTooLongPkts: + value->v.uint32 = snmpd_stats.inTooLong; + break; + + case LEAF_begemotSnmpdStatsInBadPduTypes: + value->v.uint32 = snmpd_stats.inBadPduTypes; + break; + + default: + return (SNMP_ERR_NOSUCHNAME); + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_SET: + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + case SNMP_OP_GETNEXT: + abort(); + } + abort(); +} + +/* + * SNMPd configuration scalars + */ +int +op_snmpd_config(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + switch (which) { + + case LEAF_begemotSnmpdTransmitBuffer: + value->v.integer = snmpd.txbuf; + break; + case LEAF_begemotSnmpdReceiveBuffer: + value->v.integer = snmpd.rxbuf; + break; + case LEAF_begemotSnmpdCommunityDisable: + value->v.integer = TRUTH_MK(snmpd.comm_dis); + break; + case LEAF_begemotSnmpdTrap1Addr: + return (ip_get(value, snmpd.trap1addr)); + case LEAF_begemotSnmpdVersionEnable: + value->v.uint32 = snmpd.version_enable; + break; + default: + return (SNMP_ERR_NOSUCHNAME); + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_SET: + switch (which) { + + case LEAF_begemotSnmpdTransmitBuffer: + ctx->scratch->int1 = snmpd.txbuf; + if (value->v.integer < 484 || + value->v.integer > 65535) + return (SNMP_ERR_WRONG_VALUE); + snmpd.txbuf = value->v.integer; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotSnmpdReceiveBuffer: + ctx->scratch->int1 = snmpd.rxbuf; + if (value->v.integer < 484 || + value->v.integer > 65535) + return (SNMP_ERR_WRONG_VALUE); + snmpd.rxbuf = value->v.integer; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotSnmpdCommunityDisable: + ctx->scratch->int1 = snmpd.comm_dis; + if (!TRUTH_OK(value->v.integer)) + return (SNMP_ERR_WRONG_VALUE); + if (TRUTH_GET(value->v.integer)) { + snmpd.comm_dis = 1; + } else { + if (snmpd.comm_dis) + return (SNMP_ERR_WRONG_VALUE); + } + return (SNMP_ERR_NOERROR); + + case LEAF_begemotSnmpdTrap1Addr: + return (ip_save(value, ctx, snmpd.trap1addr)); + + case LEAF_begemotSnmpdVersionEnable: + if (community != COMM_INITIALIZE) + return (SNMP_ERR_NOT_WRITEABLE); + ctx->scratch->int1 = snmpd.version_enable; + if (value->v.uint32 == 0 || + (value->v.uint32 & ~VERS_ENABLE_ALL)) + return (SNMP_ERR_WRONG_VALUE); + snmpd.version_enable = value->v.uint32; + return (SNMP_ERR_NOERROR); + } + abort(); + + case SNMP_OP_ROLLBACK: + switch (which) { + + case LEAF_begemotSnmpdTransmitBuffer: + snmpd.rxbuf = ctx->scratch->int1; + return (SNMP_ERR_NOERROR); + case LEAF_begemotSnmpdReceiveBuffer: + snmpd.txbuf = ctx->scratch->int1; + return (SNMP_ERR_NOERROR); + case LEAF_begemotSnmpdCommunityDisable: + snmpd.comm_dis = ctx->scratch->int1; + return (SNMP_ERR_NOERROR); + case LEAF_begemotSnmpdTrap1Addr: + ip_rollback(ctx, snmpd.trap1addr); + return (SNMP_ERR_NOERROR); + case LEAF_begemotSnmpdVersionEnable: + snmpd.version_enable = ctx->scratch->int1; + return (SNMP_ERR_NOERROR); + } + abort(); + + case SNMP_OP_COMMIT: + switch (which) { + + case LEAF_begemotSnmpdTransmitBuffer: + case LEAF_begemotSnmpdReceiveBuffer: + case LEAF_begemotSnmpdCommunityDisable: + return (SNMP_ERR_NOERROR); + case LEAF_begemotSnmpdTrap1Addr: + ip_commit(ctx); + return (SNMP_ERR_NOERROR); + case LEAF_begemotSnmpdVersionEnable: + return (SNMP_ERR_NOERROR); + } + abort(); + } + abort(); +} + +/* + * The community table + */ +int +op_community(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + struct asn_oid idx; + struct community *c; + asn_subid_t which = value->var.subs[sub - 1]; + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((community != COMM_INITIALIZE && snmpd.comm_dis) || + (c = NEXT_OBJECT_OID(&community_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &c->index); + break; + + case SNMP_OP_GET: + if ((community != COMM_INITIALIZE && snmpd.comm_dis) || + (c = FIND_OBJECT_OID(&community_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if (community != COMM_INITIALIZE && snmpd.comm_dis) + return (SNMP_ERR_NOT_WRITEABLE); + idx.len = 2; + idx.subs[0] = 0; + idx.subs[1] = value->var.subs[value->var.len - 1]; + switch (which) { + case LEAF_begemotSnmpdCommunityString: + /* check that given string is unique */ + TAILQ_FOREACH(c, &community_list, link) { + if (!asn_compare_oid(&idx, &c->index)) + continue; + if (c->string != NULL && strcmp(c->string, + value->v.octetstring.octets) == 0) + return (SNMP_ERR_WRONG_VALUE); + } + case LEAF_begemotSnmpdCommunityPermission: + break; + default: + return (SNMP_ERR_NOT_WRITEABLE); + } + if ((c = FIND_OBJECT_OID(&community_list, &value->var, + sub)) == NULL) { + /* create new community and use user sepcified index */ + c = comm_define_ordered(COMM_READ, "SNMP Custom Community", + &idx, NULL, NULL); + if (c == NULL) + return (SNMP_ERR_NO_CREATION); + } + switch (which) { + case LEAF_begemotSnmpdCommunityString: + return (string_save(value, ctx, -1, &c->string)); + case LEAF_begemotSnmpdCommunityPermission: + if (value->v.integer != COMM_READ && + value->v.integer != COMM_WRITE) + return (SNMP_ERR_WRONG_VALUE); + c->private = value->v.integer; + break; + default: + return (SNMP_ERR_NOT_WRITEABLE); + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + if (which == LEAF_begemotSnmpdCommunityString) { + if ((c = FIND_OBJECT_OID(&community_list, &value->var, + sub)) == NULL) + string_free(ctx); + else + string_rollback(ctx, &c->string); + return (SNMP_ERR_NOERROR); + } + if (which == LEAF_begemotSnmpdCommunityPermission) + return (SNMP_ERR_NOERROR); + abort(); + + case SNMP_OP_COMMIT: + if (which == LEAF_begemotSnmpdCommunityString) { + if ((c = FIND_OBJECT_OID(&community_list, &value->var, + sub)) == NULL) + string_free(ctx); + else + string_commit(ctx); + return (SNMP_ERR_NOERROR); + } + if (which == LEAF_begemotSnmpdCommunityPermission) + return (SNMP_ERR_NOERROR); + abort(); + + default: + abort(); + } + + switch (which) { + + case LEAF_begemotSnmpdCommunityString: + return (string_get(value, c->string, -1)); + + case LEAF_begemotSnmpdCommunityDescr: + return (string_get(value, c->descr, -1)); + + case LEAF_begemotSnmpdCommunityPermission: + value->v.integer = c->private; + return (SNMP_ERR_NOERROR); + default: + return (SNMP_ERR_NOT_WRITEABLE); + } + abort(); +} + +/* + * Module table. + */ +struct module_dep { + struct snmp_dependency dep; + u_char section[LM_SECTION_MAX + 1]; + u_char *path; + struct lmodule *m; +}; + +static int +dep_modules(struct snmp_context *ctx, struct snmp_dependency *dep, + enum snmp_depop op) +{ + struct module_dep *mdep = (struct module_dep *)(void *)dep; + + switch (op) { + + case SNMP_DEPOP_COMMIT: + if (mdep->path == NULL) { + /* unload - find the module */ + TAILQ_FOREACH(mdep->m, &lmodules, link) + if (strcmp(mdep->m->section, + mdep->section) == 0) + break; + if (mdep->m == NULL) + /* no such module - that's ok */ + return (SNMP_ERR_NOERROR); + + /* handle unloading in the finalizer */ + return (SNMP_ERR_NOERROR); + } + /* load */ + if ((mdep->m = lm_load(mdep->path, mdep->section)) == NULL) { + /* could not load */ + return (SNMP_ERR_RES_UNAVAIL); + } + /* start in finalizer */ + return (SNMP_ERR_NOERROR); + + case SNMP_DEPOP_ROLLBACK: + if (mdep->path == NULL) { + /* rollback unload - the finalizer takes care */ + return (SNMP_ERR_NOERROR); + } + /* rollback load */ + lm_unload(mdep->m); + return (SNMP_ERR_NOERROR); + + case SNMP_DEPOP_FINISH: + if (mdep->path == NULL) { + if (mdep->m != NULL && ctx->code == SNMP_RET_OK) + lm_unload(mdep->m); + } else { + if (mdep->m != NULL && ctx->code == SNMP_RET_OK && + community != COMM_INITIALIZE) + lm_start(mdep->m); + free(mdep->path); + } + return (SNMP_ERR_NOERROR); + } + abort(); +} + +int +op_modules(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + struct lmodule *m; + u_char *section, *ptr; + size_t seclen; + struct module_dep *mdep; + struct asn_oid idx; + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((m = NEXT_OBJECT_OID(&lmodules, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &m->index); + break; + + case SNMP_OP_GET: + if ((m = FIND_OBJECT_OID(&lmodules, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + m = FIND_OBJECT_OID(&lmodules, &value->var, sub); + if (which != LEAF_begemotSnmpdModulePath) { + if (m == NULL) + return (SNMP_ERR_NO_CREATION); + return (SNMP_ERR_NOT_WRITEABLE); + } + + /* the errors in the next few statements can only happen when + * m is NULL, hence the NO_CREATION error. */ + if (index_decode(&value->var, sub, iidx, + §ion, &seclen)) + return (SNMP_ERR_NO_CREATION); + + /* check the section name */ + if (seclen > LM_SECTION_MAX || seclen == 0) { + free(section); + return (SNMP_ERR_NO_CREATION); + } + for (ptr = section; ptr < section + seclen; ptr++) + if (!isascii(*ptr) || !isalnum(*ptr)) { + free(section); + return (SNMP_ERR_NO_CREATION); + } + if (!isalpha(section[0])) { + free(section); + return (SNMP_ERR_NO_CREATION); + } + + /* check the path */ + for (ptr = value->v.octetstring.octets; + ptr < value->v.octetstring.octets + value->v.octetstring.len; + ptr++) { + if (*ptr == '\0') { + free(section); + return (SNMP_ERR_WRONG_VALUE); + } + } + + if (m == NULL) { + if (value->v.octetstring.len == 0) { + free(section); + return (SNMP_ERR_INCONS_VALUE); + } + } else { + if (value->v.octetstring.len != 0) { + free(section); + return (SNMP_ERR_INCONS_VALUE); + } + } + + asn_slice_oid(&idx, &value->var, sub, value->var.len); + + /* so far, so good */ + mdep = (struct module_dep *)(void *)snmp_dep_lookup(ctx, + &oid_begemotSnmpdModuleTable, &idx, + sizeof(*mdep), dep_modules); + if (mdep == NULL) { + free(section); + return (SNMP_ERR_RES_UNAVAIL); + } + + if (mdep->section[0] != '\0') { + /* two writes to the same entry - bad */ + free(section); + return (SNMP_ERR_INCONS_VALUE); + } + + strncpy(mdep->section, section, seclen); + mdep->section[seclen] = '\0'; + free(section); + + if (value->v.octetstring.len == 0) + mdep->path = NULL; + else { + if ((mdep->path = malloc(value->v.octetstring.len + 1)) == NULL) + return (SNMP_ERR_RES_UNAVAIL); + strncpy(mdep->path, value->v.octetstring.octets, + value->v.octetstring.len); + mdep->path[value->v.octetstring.len] = '\0'; + } + ctx->scratch->ptr1 = mdep; + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + + default: + abort(); + } + + switch (which) { + + case LEAF_begemotSnmpdModulePath: + return (string_get(value, m->path, -1)); + + case LEAF_begemotSnmpdModuleComment: + return (string_get(value, m->config->comment, -1)); + } + abort(); +} + +int +op_snmp_set(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + switch (value->var.subs[sub - 1]) { + + case LEAF_snmpSetSerialNo: + value->v.integer = snmp_serial_no; + break; + + default: + abort(); + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_SET: + switch (value->var.subs[sub - 1]) { + + case LEAF_snmpSetSerialNo: + if (value->v.integer != snmp_serial_no) + return (SNMP_ERR_INCONS_VALUE); + break; + + default: + abort(); + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + if (snmp_serial_no++ == 2147483647) + snmp_serial_no = 0; + return (SNMP_ERR_NOERROR); + } + abort(); +} + +/* + * SNMP Engine + */ +int +op_snmp_engine(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + + switch (op) { + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + break; + + case SNMP_OP_SET: + if (community != COMM_INITIALIZE) + return (SNMP_ERR_NOT_WRITEABLE); + switch (which) { + case LEAF_snmpEngineID: + if (value->v.octetstring.len > SNMP_ENGINE_ID_SIZ) + return (SNMP_ERR_WRONG_VALUE); + ctx->scratch->ptr1 = malloc(snmpd_engine.engine_len); + if (ctx->scratch->ptr1 == NULL) + return (SNMP_ERR_GENERR); + memcpy(ctx->scratch->ptr1, snmpd_engine.engine_id, + snmpd_engine.engine_len); + ctx->scratch->int1 = snmpd_engine.engine_len; + snmpd_engine.engine_len = value->v.octetstring.len; + memcpy(snmpd_engine.engine_id, + value->v.octetstring.octets, + value->v.octetstring.len); + break; + + case LEAF_snmpEngineMaxMessageSize: + ctx->scratch->int1 = snmpd_engine.max_msg_size; + snmpd_engine.max_msg_size = value->v.integer; + break; + + default: + return (SNMP_ERR_NOT_WRITEABLE); + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + switch (which) { + case LEAF_snmpEngineID: + snmpd_engine.engine_len = ctx->scratch->int1; + memcpy(snmpd_engine.engine_id, ctx->scratch->ptr1, + snmpd_engine.engine_len); + free(ctx->scratch->ptr1); + break; + + case LEAF_snmpEngineMaxMessageSize: + snmpd_engine.max_msg_size = ctx->scratch->int1; + break; + + default: + abort(); + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + if (which == LEAF_snmpEngineID) { + if (set_snmpd_engine() < 0) { + snmpd_engine.engine_len = ctx->scratch->int1; + memcpy(snmpd_engine.engine_id, + ctx->scratch->ptr1, ctx->scratch->int1); + } + free(ctx->scratch->ptr1); + } + return (SNMP_ERR_NOERROR); + } + + + switch (which) { + case LEAF_snmpEngineID: + return (string_get(value, snmpd_engine.engine_id, + snmpd_engine.engine_len)); + case LEAF_snmpEngineBoots: + value->v.integer = snmpd_engine.engine_boots; + break; + case LEAF_snmpEngineTime: + update_snmpd_engine_time(); + value->v.integer = snmpd_engine.engine_time; + break; + case LEAF_snmpEngineMaxMessageSize: + value->v.integer = snmpd_engine.max_msg_size; + break; + default: + return (SNMP_ERR_NOSUCHNAME); + } + + return (SNMP_ERR_NOERROR); +} + +/* + * Transport table + */ +int +op_transport_table(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + struct transport *t; + u_char *tname, *ptr; + size_t tnamelen; + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((t = NEXT_OBJECT_OID(&transport_list, &value->var, sub)) + == NULL) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &t->index); + break; + + case SNMP_OP_GET: + if ((t = FIND_OBJECT_OID(&transport_list, &value->var, sub)) + == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + t = FIND_OBJECT_OID(&transport_list, &value->var, sub); + if (which != LEAF_begemotSnmpdTransportStatus) { + if (t == NULL) + return (SNMP_ERR_NO_CREATION); + return (SNMP_ERR_NOT_WRITEABLE); + } + + /* the errors in the next few statements can only happen when + * t is NULL, hence the NO_CREATION error. */ + if (index_decode(&value->var, sub, iidx, + &tname, &tnamelen)) + return (SNMP_ERR_NO_CREATION); + + /* check the section name */ + if (tnamelen >= TRANS_NAMELEN || tnamelen == 0) { + free(tname); + return (SNMP_ERR_NO_CREATION); + } + for (ptr = tname; ptr < tname + tnamelen; ptr++) { + if (!isascii(*ptr) || !isalnum(*ptr)) { + free(tname); + return (SNMP_ERR_NO_CREATION); + } + } + + /* for now */ + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + default: + abort(); + } + + switch (which) { + + case LEAF_begemotSnmpdTransportStatus: + value->v.integer = 1; + break; + + case LEAF_begemotSnmpdTransportOid: + memcpy(&value->v.oid, &t->vtab->id, sizeof(t->vtab->id)); + break; + } + return (SNMP_ERR_NOERROR); +} Property changes on: vendor/bsnmp/1.13/snmpd/action.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/bsnmpd.1 =================================================================== --- vendor/bsnmp/1.13/snmpd/bsnmpd.1 (nonexistent) +++ vendor/bsnmp/1.13/snmpd/bsnmpd.1 (revision 336778) @@ -0,0 +1,280 @@ +.\" +.\" Copyright (c) 2004-2005 +.\" Hartmut Brandt. +.\" All rights reserved. +.\" Copyright (c) 2001-2003 +.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus). +.\" All rights reserved. +.\" +.\" Author: Harti Brandt +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Begemot: bsnmp/snmpd/bsnmpd.1,v 1.12 2006/02/27 09:50:03 brandt_h Exp $ +.\" +.Dd May 14, 2016 +.Dt BSNMPD 1 +.Os +.Sh NAME +.Nm bsnmpd +.Nd "simple and extensible SNMP daemon" +.Sh SYNOPSIS +.Nm +.Op Fl dh +.Op Fl c Ar file +.Op Fl D Ar options +.Op Fl e Ar file +.Op Fl I Ar paths +.Op Fl l Ar prefix +.Op Fl m Ar variable Ns Op = Ns Ar value +.Op Fl p Ar file +.Sh DESCRIPTION +The +.Nm +daemon serves the internet SNMP (Simple Network Management Protocol). +It is intended to serve only the absolute basic MIBs and implement all other +MIBs through loadable modules. +In this way the +.Nm +can be used in unexpected ways. +.Pp +The options are as follows: +.Bl -tag -width ".It Fl D Ar options" +.It Fl d +Do not daemonize. +Used for debugging. +.It Fl h +Print a short usage message. +.It Fl c Ar file +Use +.Ar file +as configuration file instead of the standard one. +.It Fl D Ar options +Debugging options are specified with a +.Fl o +flag followed by a comma separated string of options. +The following options are available. +.Bl -tag -width ".It Cm trace Ns Cm = Ns Cm level" +.It Cm dump +Dump all sent and received PDUs to the terminal. +.It Cm events +Set the debugging level of the event library (see +.Xr eventlib 3 ) +to 10. +.It Cm trace Ns Cm = Ns Cm level +Set the snmp library trace flag to the specified +value. +.El +The value can be specified in the usual C-syntax for numbers. +.It Fl e Ar file +Specify an alternate file where the agent's engine id and number of boots +are saved. +.It Fl I Ar paths +Specify a colon separated list of directories to search for configuration +include files. +The default is +.Pa /etc:/usr/etc/:/usr/local/etc . +These paths are only searched for include specified within <> parentheses. +.It Fl l Ar prefix +Use +.Ar prefix +as the default basename for the pid and the configuration files. +.It Fl m Ar variable Ns Op = Ns Ar value +Define a configuration variable. +.It Fl p Ar file +Specify an alternate pid file instead of the default one. +.El +.Sh CONFIGURATION +.Nm +reads its configuration from either the default or the user specified +configuration file. +The configuration file consists of the following types of lines: +.Bl -bullet -offset indent +.It +variable assignments +.It +section separators +.It +include directives +.It +MIB variable assignments +.El +.Pp +If a line is too long it can be continued on the next line by ending it with +a backslash. +Empty lines and lines in which the first non-blank character is a +.Dq # +sign are ignored. +.Pp +All MIB variable assignments of the entire configuration (including nested +configuration files) are handled as one transaction, i.e., as if they arrived +in a single SET PDU. +Any failure during the initial configuration read causes +.Nm +to exit. +A failure during the configuration read caused by a module load +causes the loading of the module to fail. +.Pp +The configuration is read during initialization of +.Nm , +when a module is loaded and when +.Nm +receives a SIGHUP. +.Ss VARIABLE ASSIGNMENTS +Variable assignments can take one of two forms: +.Bd -unfilled -offset indent +variable := string +variable ?= string +.Ed +.Pp +The string reaches from the first non-blank character after the +equal sign until the first new line or +.Dq # +character. +In the first case +the string is assigned to the variable unconditionally, in the second case the +variable is only assigned if it does not exist yet. +.Pp +Variable names must begin with a letter or underscore and contain only letters, +digits or underscores. +.Ss SECTION SEPARATORS +The configuration consists of named sections. +The MIB variable assignments in the section named +.Dq snmpd +are executed only during initial setup or when +.Nm +receives a SIGHUP. +All other sections are executed when either a module +with the same name as the section is loaded or +.Nm +receives a SIGHUP and that module is already loaded. +The default section at the start of the configuration is +.Dq snmpd . +One can switch to another section with the syntax +.Bd -unfilled -offset indent +%secname +.Ed +.Pp +Where +.Ar secname +is the name of the section. +The same +.Ar secname +can be used in more than one place in the configuration. +All of these parts are collected into one section. +.Ss INCLUDE DIRECTIVES +Another configuration file can be included into the current one with the +include directive that takes one of two forms: +.Bd -unfilled -offset indent +\&.include "file" +\&.include <"file"> +.Ed +.Pp +The first form causes the file to be searched in the current directory, the +second form causes the file to be searched in the directories specified in +the system include path. +Nesting depth is only restricted by available memory. +.Ss MIB VARIABLE ASSIGNMENTS +A MIB variable is assigned with the syntax +.Bd -unfilled -offset indent +oid [ suboids ] = value +.Ed +.Pp +.Va oid +is the name of the variable to be set. +Only the last component of the entire name is used here. +If the variable is a scalar, the index (.0) is automatically +appended and need not to be specified. +If the variable is a table column, the index +.Pq Va suboids +must be specified. +The index consist of elements each separated from the +previous one by a dot. +Elements may be either numbers, strings or hostnames +enclosed in [] brackets. +If the element is a number it is appended +to the current oid. +If the element is a string, its length and the +.Tn ASCII +code of each of its characters are appended to the current oid. +If the +element is a hostname, the IP address of the host is looked up and the four +elements of the IP address are appended to the oid. +.Pp +For example, an oid of +.Bd -unfilled -offset indent +myvariable.27.foooll.[localhost]."&^!" +.Ed +.Pp +results in the oid +.Bd -unfilled -offset indent +myvariable.27.102.111.111.111.108.108.127.0.0.1.38.94.33 +.Ed +.Pp +The value of the assignment may be either empty, a string or a number. +If a string starts with a letter or an underscore and consists only of +letters, digits, underscores and minus signs, it can be written without +quotes. +In all other cases the string must be enclosed in double quotes. +.Sh SUBSTITUTIONS +A variable substitution is written as +.Bd -unfilled -offset indent +$(variable) +.Ed +.Pp +where +.Ar variable +is the name of the variable to substitute. +Using an undefined variable is considered an error. +.Sh FILES +.Bl -tag -width ".It Pa /var/run/ Ns Ao Ar prefix Ac Ns \&.pid" -compact +.It Pa /etc/ Ns Ao Ar prefix Ac Ns \&.config +Default configuration file, where the default +.Aq prefix +is +.Dq snmpd . +.It Pa /var/ Ns Ao Ar prefix Ac Ns \&.engine +Default engine id file. +.It Pa /var/run/ Ns Ao Ar prefix Ac Ns \&.pid +Default pid file. +.It Pa /etc:/usr/etc/:/usr/local/etc +Default search path for system include files. +.It Pa @MIBSPATH@FOKUS-MIB.txt +.It Pa @MIBSPATH@BEGEMOT-MIB.txt +.It Pa @MIBSPATH@BEGEMOT-SNMPD.txt +Definitions for the MIBs implemented in the daemon. +.It Pa /etc/hosts.allow, /etc/hosts.deny +Access controls that should be enforced by TCP wrappers are defined here. +Further details are described in +.Xr hosts_access 5 . +.El +.Sh SEE ALSO +.Xr gensnmptree 1 , +.Xr hosts_access 5 +.Sh STANDARDS +The +.Nm +conforms to the applicable IETF RFCs. +.Sh AUTHORS +.An Hartmut Brandt Aq harti@FreeBSD.org +.Sh BUGS +Sure. Property changes on: vendor/bsnmp/1.13/snmpd/bsnmpd.1 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/config.c =================================================================== --- vendor/bsnmp/1.13/snmpd/config.c (nonexistent) +++ vendor/bsnmp/1.13/snmpd/config.c (revision 336778) @@ -0,0 +1,1383 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmpd/config.c,v 1.25 2006/02/14 09:04:20 brandt_h Exp $ + * + * Parse configuration file. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "snmpmod.h" +#include "snmpd.h" +#include "tree.h" + +/* +#define DEBUGGING +*/ + +/* + * config_file: EMPTY | config_file line + * + * line: oid '=' value + * | '%' STRING + * | STRING := REST_OF_LINE + * | STRING ?= REST_OF_LINE + * | . INCLUDE STRING + * + * oid: STRING suboid + * + * suboid: EMPTY | suboid '.' subid + * + * subid: NUM | STRING | '[' STRING ']' + * + * value: EMPTY | STRING | NUM + */ + +/* + * Input context for macros and includes + */ +enum input_type { + INPUT_FILE = 1, + INPUT_STRING +}; +struct input { + enum input_type type; + union { + struct { + FILE *fp; + char *filename; + u_int lno; + } file; + struct { + char *macro; + char *str; + char *ptr; + size_t left; + } str; + } u; + LIST_ENTRY(input) link; +}; +static LIST_HEAD(, input) inputs; + +#define input_fp u.file.fp +#define input_filename u.file.filename +#define input_lno u.file.lno +#define input_macro u.str.macro +#define input_str u.str.str +#define input_ptr u.str.ptr +#define input_left u.str.left + +static int input_push; +static int input_buf[2]; + +/* + * Configuration data. The configuration file is handled as one single + * SNMP transaction. So we need to keep the assignment data for the + * commit or rollback pass. Note, that dependencies and finish functions + * are NOT allowed here. + */ +struct assign { + struct snmp_value value; + struct snmp_scratch scratch; + const char *node_name; + + TAILQ_ENTRY(assign) link; +}; +static TAILQ_HEAD(assigns, assign) assigns = TAILQ_HEAD_INITIALIZER(assigns); + + +static struct snmp_context *snmp_ctx; + +struct macro { + char *name; + char *value; + size_t length; + LIST_ENTRY(macro) link; + int perm; +}; +static LIST_HEAD(, macro) macros = LIST_HEAD_INITIALIZER(macros); + +enum { + TOK_EOF = 0200, + TOK_EOL, + TOK_NUM, + TOK_STR, + TOK_HOST, + TOK_ASSIGN, + TOK_QASSIGN, +}; + +/* lexer values and last token */ +static uint64_t numval; +static char strval[_POSIX2_LINE_MAX]; +static size_t strvallen; +static int token; + +/* error return */ +static jmp_buf errjmp[4]; +static volatile int errstk; + +# define ERRPUSH() (setjmp(errjmp[errstk++])) +# define ERRPOP() ((void)(errstk--)) +# define ERRNEXT() (longjmp(errjmp[--errstk], 1)) +# define ERR() (longjmp(errjmp[--errstk], 1)) + +/* section context */ +static int ignore; + +/* + * Report an error and jump to the error label + */ +static void report(const char *fmt, ...) __dead2 __printflike(1, 2); + +static void +report(const char *fmt, ...) +{ + va_list ap; + const struct input *input; + + va_start(ap, fmt); + vsyslog(LOG_ERR, fmt, ap); + va_end(ap); + + LIST_FOREACH(input, &inputs, link) { + switch (input->type) { + + case INPUT_FILE: + syslog(LOG_ERR, " in file %s line %u", + input->input_filename, input->input_lno); + break; + + case INPUT_STRING: + syslog(LOG_ERR, " in macro %s pos %td", + input->input_macro, + input->input_ptr - input->input_str); + break; + } + } + ERR(); +} + +/* + * Open a file for input + */ +static int +input_open_file(const char *fname, int sysdir) +{ + struct input *input; + FILE *fp; + char path[PATH_MAX + 1]; + const char *col; + const char *ptr; + + if (sysdir) { + ptr = syspath; + fp = NULL; + while (*ptr != '\0') { + if ((col = strchr(ptr, ':')) == NULL) { + snprintf(path, sizeof(path), "%s/%s", + ptr, fname); + col = ptr + strlen(ptr) - 1; + } else if (col == ptr) + snprintf(path, sizeof(path), "./%s", fname); + else + snprintf(path, sizeof(path), "%.*s/%s", + (int)(col - ptr), ptr, fname); + if ((fp = fopen(path, "r")) != NULL) + break; + ptr = col + 1; + } + } else + fp = fopen(fname, "r"); + + if (fp == NULL) + report("%s: %m", fname); + + if ((input = malloc(sizeof(*input))) == NULL) { + fclose(fp); + return (-1); + } + if ((input->input_filename = malloc(strlen(fname) + 1)) == NULL) { + fclose(fp); + free(input); + return (-1); + } + strcpy(input->input_filename, fname); + input->input_fp = fp; + input->input_lno = 1; + input->type = INPUT_FILE; + LIST_INSERT_HEAD(&inputs, input, link); + return (0); +} + +/* + * Make a macro the next input + */ +static void +input_open_macro(struct macro *m) +{ + struct input *input; + + if ((input = malloc(sizeof(*input))) == NULL) + report("%m"); + input->type = INPUT_STRING; + input->input_macro = m->name; + if ((input->input_str = malloc(m->length)) == NULL) { + free(input); + report("%m"); + } + memcpy(input->input_str, m->value, m->length); + input->input_ptr = input->input_str; + input->input_left = m->length; + LIST_INSERT_HEAD(&inputs, input, link); +} + +/* + * Close top input source + */ +static void +input_close(void) +{ + struct input *input; + + if ((input = LIST_FIRST(&inputs)) == NULL) + abort(); + switch (input->type) { + + case INPUT_FILE: + fclose(input->input_fp); + free(input->input_filename); + break; + + case INPUT_STRING: + free(input->input_str); + break; + } + LIST_REMOVE(input, link); + free(input); +} + +/* + * Close all inputs + */ +static void +input_close_all(void) +{ + while (!LIST_EMPTY(&inputs)) + input_close(); +} + +/* + * Push back one character + */ +static void +input_ungetc(int c) +{ + if (c == EOF) + report("pushing EOF"); + if (input_push == 2) + report("pushing third char"); + input_buf[input_push++] = c; +} + + +/* + * Return next character from the input without preprocessing. + */ +static int +input_getc_raw(void) +{ + int c; + struct input *input; + + if (input_push != 0) { + c = input_buf[--input_push]; + goto ok; + } + while ((input = LIST_FIRST(&inputs)) != NULL) { + switch (input->type) { + + case INPUT_FILE: + if ((c = getc(input->input_fp)) == EOF) { + if (ferror(input->input_fp)) + report("read error: %m"); + input_close(); + break; + } + if (c == '\n') + input->input_lno++; + goto ok; + + case INPUT_STRING: + if (input->input_left-- == 0) { + input_close(); + break; + } + c = *input->input_ptr++; + goto ok; + } + } +# ifdef DEBUGGING + fprintf(stderr, "EOF"); +# endif + return (EOF); + + ok: +# ifdef DEBUGGING + if (!isascii(c) || !isprint(c)) + fprintf(stderr, "'%#2x'", c); + else + fprintf(stderr, "'%c'", c); +# endif + return (c); +} + +/* + * Get character with and \\n -> processing. + */ +static int +input_getc_plain(void) +{ + int c; + + again: + if ((c = input_getc_raw()) == '\\') { + if ((c = input_getc_raw()) == '\n') + goto again; + if (c != EOF) + input_ungetc(c); + return ('\\'); + } + return (c); +} + +/* + * Get next character with substitution of macros + */ +static int +input_getc(void) +{ + int c; + struct macro *m; + char name[_POSIX2_LINE_MAX]; + size_t namelen; + + again: + if ((c = input_getc_plain()) != '$') + return (c); + + if ((c = input_getc()) == EOF) + report("unexpected EOF"); + if (c != '(') + report("expecting '(' after '$'"); + + namelen = 0; + while ((c = input_getc()) != EOF && c != ')') { + if (isalpha(c) || c == '_' || (namelen != 0 && isdigit(c))) + name[namelen++] = c; + else + goto badchar; + } + if (c == EOF) + report("unexpected EOF"); + name[namelen++] = '\0'; + + LIST_FOREACH(m, ¯os, link) + if (strcmp(m->name, name) == 0) + break; + if (m == NULL) + report("undefined macro '%s'", name); + + input_open_macro(m); + goto again; + + badchar: + if (!isascii(c) || !isprint(c)) + report("unexpected character %#2x", (u_int)c); + else + report("bad character '%c'", c); +} + + +static void +input_getnum(u_int base, u_int flen) +{ + int c; + u_int cnt; + + cnt = 0; + numval = 0; + while (flen == 0 || cnt < flen) { + if ((c = input_getc()) == EOF) { + if (cnt == 0) + report("bad number"); + return; + } + if (isdigit(c)) { + if (base == 8 && (c == '8' || c == '9')) { + input_ungetc(c); + if (cnt == 0) + report("bad number"); + return; + } + numval = numval * base + (c - '0'); + } else if (base == 16 && isxdigit(c)) { + if (islower(c)) + numval = numval * base + (c - 'a' + 10); + else + numval = numval * base + (c - 'A' + 10); + } else { + input_ungetc(c); + if (cnt == 0) + report("bad number"); + return; + } + cnt++; + } +} + +static int +# ifdef DEBUGGING +_gettoken(void) +# else +gettoken(void) +# endif +{ + int c; + char *end; + static const char esc[] = "abfnrtv"; + static const char chr[] = "\a\b\f\n\r\t\v"; + + /* + * Skip any whitespace before the next token + */ + while ((c = input_getc()) != EOF) { + if (!isspace(c) || c == '\n') + break; + } + if (c == EOF) + return (token = TOK_EOF); + if (!isascii(c)) + goto badchar; + + /* + * Skip comments + */ + if (c == '#') { + while ((c = input_getc_plain()) != EOF) { + if (c == '\n') + return (token = TOK_EOL); + } + goto badeof; + } + + /* + * Single character tokens + */ + if (c == '\n') + return (token = TOK_EOL); + if (c == '.' || c == '%' || c == '=' || c == '<' || c == '>') + return (token = c); + if (c == ':') { + if ((c = input_getc()) == '=') + return (token = TOK_ASSIGN); + input_ungetc(c); + return (token = ':'); + } + if (c == '?') { + if ((c = input_getc()) == '=') + return (token = TOK_QASSIGN); + input_ungetc(c); + goto badchar; + } + + /* + * Sort out numbers + */ + if (isdigit(c)) { + if (c == '0') { + if ((c = input_getc()) == 'x' || c == 'X') { + input_getnum(16, 0); + } else if (isdigit(c)) { + input_ungetc(c); + input_getnum(8, 0); + } else { + if (c != EOF) + input_ungetc(c); + numval = 0; + c = 1; + } + } else { + input_ungetc(c); + input_getnum(10, 0); + } + return (token = TOK_NUM); + } + + /* + * Must be a string then + */ + strvallen = 0; + +# define GETC(C) do { \ + if ((c = input_getc()) == EOF) \ + goto badeof; \ + if (!isascii(c) || (!isprint(c) && c != '\t')) \ + goto badchar; \ +} while(0) + + if (c == '"') { + for(;;) { + GETC(c); + if (c == '"') { + strval[strvallen] = '\0'; + break; + } + if (c != '\\') { + strval[strvallen++] = c; + continue; + } + GETC(c); + if ((end = strchr(esc, c)) != NULL) { + strval[strvallen++] = chr[end - esc]; + continue; + } + if (c == 'x') { + input_getnum(16, 2); + c = numval; + } else if (c >= '0' && c <= '7') { + input_ungetc(c); + input_getnum(8, 3); + c = numval; + } + strval[strvallen++] = c; + } +# undef GETC + + } else if (c == '[') { + /* + * Skip leading space + */ + while ((c = input_getc()) != EOF && isspace(c)) + ; + if (c == EOF) + goto badeof; + while (c != ']' && !isspace(c)) { + if (!isalnum(c) && c != '.' && c != '-') + goto badchar; + strval[strvallen++] = c; + if ((c = input_getc()) == EOF) + goto badeof; + } + while (c != ']' && isspace(c)) { + if ((c = input_getc()) == EOF) + goto badeof; + } + if (c != ']') + goto badchar; + strval[strvallen] = '\0'; + return (token = TOK_HOST); + + } else if (!isalpha(c) && c != '_') { + goto badchar; + + } else { + for (;;) { + strval[strvallen++] = c; + if ((c = input_getc()) == EOF) + goto badeof; + if (!isalnum(c) && c != '_' && c != '-') { + input_ungetc(c); + strval[strvallen] = '\0'; + break; + } + } + } + + return (token = TOK_STR); + + badeof: + report("unexpected EOF"); + + badchar: + if (!isascii(c) || !isprint(c)) + report("unexpected character %#2x", (u_int)c); + else + report("bad character '%c'", c); +} + +# ifdef DEBUGGING +static int +gettoken() +{ + _gettoken(); + if (isascii(token) && isprint(token)) + printf("(%c)", token); + else { + switch (token) { + + case TOK_EOF: + printf("(EOF)"); + break; + case TOK_EOL: + printf("(EOL)"); + break; + case TOK_NUM: + printf("(NUM %ju)", (uintmax_t)numval); + break; + case TOK_STR: + printf("(STR %.*s)", (int)strvallen, strval); + break; + case TOK_HOST: + printf("(HOST %s)", strval); + break; + default: + printf("(%#2x)", token); + break; + } + } + return (token); +} +#endif + + +/* + * Try to execute the assignment. + */ +static void +handle_assignment(const struct snmp_node *node, struct asn_oid *vindex, + const struct snmp_value *value) +{ + u_int i; + int err; + struct assign *tp; + char nodename[100]; + + if (node->type == SNMP_NODE_LEAF) { + /* index must be one single zero or no index at all */ + if (vindex->len > 1 || (vindex->len == 1 && + vindex->subs[0] != 0)) + report("bad index on leaf node"); + vindex->len = 1; + vindex->subs[0] = 0; + } else { + /* resulting oid must not be too long */ + if (node->oid.len + vindex->len > ASN_MAXOIDLEN) + report("resulting OID too long"); + } + + /* + * Get the next assignment entry for the transaction. + */ + if ((tp = malloc(sizeof(*tp))) == NULL) + report("%m"); + + tp->value = *value; + tp->node_name = node->name; + + /* + * Build the OID + */ + tp->value.var = node->oid; + for (i = 0; i < vindex->len; i++) + tp->value.var.subs[tp->value.var.len++] = vindex->subs[i]; + + /* + * Puzzle together the variables for the call and call the + * set routine. The set routine may make our node pointer + * invalid (if we happend to call the module loader) so + * get a copy of the node name beforehands. + */ + snprintf(nodename, sizeof(nodename), "%s", node->name); + snmp_ctx->scratch = &tp->scratch; + snmp_ctx->var_index = 0; + err = (*node->op)(snmp_ctx, &tp->value, node->oid.len, node->index, + SNMP_OP_SET); + if (err != 0) { + free(tp); + report("assignment to %s.%s returns %d", nodename, + asn_oid2str(vindex), err); + } + + TAILQ_INSERT_TAIL(&assigns, tp, link); +} + + +/* + * Parse the section statement + */ +static void +parse_section(const struct lmodule *mod) +{ + if (token != TOK_STR) + report("expecting section name"); + + if (strcmp(strval, "snmpd") == 0) { + if (mod != NULL) + /* loading a module - ignore common stuff */ + ignore = 1; + else + /* global configuration - don't ignore */ + ignore = 0; + } else { + if (mod == NULL) { + /* global configuration - ignore module stuff */ + ignore = 1; + } else { + /* loading module - check if it's our section */ + ignore = (strcmp(strval, mod->section) != 0); + } + } + gettoken(); +} + +/* + * Convert a hostname to four u_chars + */ +static void +gethost(const char *host, u_char *ip) +{ + struct addrinfo hints, *res; + int error; + struct sockaddr_in *sain; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_flags = AI_PASSIVE; + error = getaddrinfo(host, NULL, &hints, &res); + if (error != 0) + report("%s: %s", host, gai_strerror(error)); + if (res == NULL) + report("%s: unknown hostname", host); + + sain = (struct sockaddr_in *)(void *)res->ai_addr; + sain->sin_addr.s_addr = ntohl(sain->sin_addr.s_addr); + ip[0] = sain->sin_addr.s_addr >> 24; + ip[1] = sain->sin_addr.s_addr >> 16; + ip[2] = sain->sin_addr.s_addr >> 8; + ip[3] = sain->sin_addr.s_addr >> 0; + + freeaddrinfo(res); +} + +/* + * Parse the left hand side of a config line. + */ +static const struct snmp_node * +parse_oid(const char *varname, struct asn_oid *oid) +{ + struct snmp_node *node; + u_int i; + u_char ip[4]; + struct asn_oid str_oid; + + for (node = tree; node < &tree[tree_size]; node++) + if (strcmp(varname, node->name) == 0) + break; + if (node == &tree[tree_size]) + node = NULL; + + oid->len = 0; + while (token == '.') { + if (gettoken() == TOK_NUM) { + if (numval > ASN_MAXID) + report("subid too large %#jx", + (uintmax_t)numval); + if (oid->len == ASN_MAXOIDLEN) + report("index too long"); + if (gettoken() != ':') + oid->subs[oid->len++] = numval; + else { + str_oid.len = 0; + str_oid.subs[str_oid.len++] = numval; + while (gettoken() == TOK_NUM) { + str_oid.subs[str_oid.len++] = numval; + if (gettoken() != ':') + break; + } + oid->subs[oid->len++] = str_oid.len; + asn_append_oid(oid, &str_oid); + } + + } else if (token == TOK_STR) { + if (strvallen + oid->len + 1 > ASN_MAXOIDLEN) + report("oid too long"); + oid->subs[oid->len++] = strvallen; + for (i = 0; i < strvallen; i++) + oid->subs[oid->len++] = strval[i]; + gettoken(); + + } else if (token == TOK_HOST) { + gethost(strval, ip); + if (oid->len + 4 > ASN_MAXOIDLEN) + report("index too long"); + for (i = 0; i < 4; i++) + oid->subs[oid->len++] = ip[i]; + gettoken(); + } else + report("bad token in index"); + } + + return (node); +} + +/* + * Parse the value for an assignment. + */ +static void +parse_syntax_null(struct snmp_value *value __unused) +{ + if (token != TOK_EOL) + report("bad NULL syntax"); +} + +static void +parse_syntax_integer(struct snmp_value *value) +{ + if (token != TOK_NUM) + report("bad INTEGER syntax"); + if (numval > 0x7fffffff) + report("INTEGER too large %ju", (uintmax_t)numval); + + value->v.integer = numval; + gettoken(); +} + +static void +parse_syntax_counter64(struct snmp_value *value) +{ + if (token != TOK_NUM) + report("bad COUNTER64 syntax"); + + value->v.counter64 = numval; + gettoken(); +} + +static void +parse_syntax_octetstring(struct snmp_value *value) +{ + u_long alloc; + u_char *noct; + + if (token == TOK_STR) { + value->v.octetstring.len = strvallen; + value->v.octetstring.octets = malloc(strvallen); + (void)memcpy(value->v.octetstring.octets, strval, strvallen); + gettoken(); + return; + } + + /* XX:XX:XX syntax */ + value->v.octetstring.octets = NULL; + value->v.octetstring.len = 0; + + if (token != TOK_NUM) + /* empty string is allowed */ + return; + + if (ERRPUSH()) { + free(value->v.octetstring.octets); + ERRNEXT(); + } + + alloc = 0; + for (;;) { + if (token != TOK_NUM) + report("bad OCTETSTRING syntax"); + if (numval > 0xff) + report("byte value too large"); + if (alloc == value->v.octetstring.len) { + alloc += 100; + noct = realloc(value->v.octetstring.octets, alloc); + if (noct == NULL) + report("%m"); + value->v.octetstring.octets = noct; + } + value->v.octetstring.octets[value->v.octetstring.len++] + = numval; + if (gettoken() != ':') + break; + gettoken(); + } + ERRPOP(); +} + +static void +parse_syntax_oid(struct snmp_value *value) +{ + value->v.oid.len = 0; + + if (token != TOK_NUM) + return; + + for (;;) { + if (token != TOK_NUM) + report("bad OID syntax"); + if (numval > ASN_MAXID) + report("subid too large"); + if (value->v.oid.len == ASN_MAXOIDLEN) + report("OID too long"); + value->v.oid.subs[value->v.oid.len++] = numval; + if (gettoken() != '.') + break; + gettoken(); + } +} + +static void +parse_syntax_ipaddress(struct snmp_value *value) +{ + int i; + u_char ip[4]; + + if (token == TOK_NUM) { + /* numerical address */ + i = 0; + for (;;) { + if (numval >= 256) + report("ip address part too large"); + value->v.ipaddress[i++] = numval; + if (i == 4) + break; + if (gettoken() != '.') + report("expecting '.' in ip address"); + } + gettoken(); + + } else if (token == TOK_HOST) { + /* host name */ + gethost(strval, ip); + for (i = 0; i < 4; i++) + value->v.ipaddress[i] = ip[i]; + gettoken(); + + } else + report("bad ip address syntax"); +} + +static void +parse_syntax_uint32(struct snmp_value *value) +{ + + if (token != TOK_NUM) + report("bad number syntax"); + if (numval > 0xffffffff) + report("number too large"); + value->v.uint32 = numval; + gettoken(); +} + +/* + * Parse an assignement line + */ +static void +parse_assign(const char *varname) +{ + struct snmp_value value; + struct asn_oid vindex; + const struct snmp_node *node; + + node = parse_oid(varname, &vindex); + if (token != '=') + report("'=' expected, got '%c'", token); + gettoken(); + + if (ignore) { + /* skip rest of line */ + while (token != TOK_EOL && token != TOK_EOF) + gettoken(); + return; + } + if (node == NULL) + report("unknown variable"); + + switch (value.syntax = node->syntax) { + + case SNMP_SYNTAX_NULL: + parse_syntax_null(&value); + break; + + case SNMP_SYNTAX_INTEGER: + parse_syntax_integer(&value); + break; + + case SNMP_SYNTAX_COUNTER64: + parse_syntax_counter64(&value); + break; + + case SNMP_SYNTAX_OCTETSTRING: + parse_syntax_octetstring(&value); + break; + + case SNMP_SYNTAX_OID: + parse_syntax_oid(&value); + break; + + case SNMP_SYNTAX_IPADDRESS: + parse_syntax_ipaddress(&value); + break; + + case SNMP_SYNTAX_COUNTER: + case SNMP_SYNTAX_GAUGE: + case SNMP_SYNTAX_TIMETICKS: + parse_syntax_uint32(&value); + break; + + case SNMP_SYNTAX_NOSUCHOBJECT: + case SNMP_SYNTAX_NOSUCHINSTANCE: + case SNMP_SYNTAX_ENDOFMIBVIEW: + abort(); + } + + if (ERRPUSH()) { + snmp_value_free(&value); + ERRNEXT(); + } + + handle_assignment(node, &vindex, &value); + + ERRPOP(); +} + +/* + * Handle macro definition line + * We have already seen the := and the input now stands at the character + * after the =. Skip whitespace and then call the input routine directly to + * eat up characters. + */ +static void +parse_define(const char *varname) +{ + char *volatile string; + char *new; + volatile size_t alloc, length; + int c; + struct macro *m; + int t = token; + + alloc = 100; + length = 0; + if ((string = malloc(alloc)) == NULL) + report("%m"); + + if (ERRPUSH()) { + free(string); + ERRNEXT(); + } + + while ((c = input_getc_plain()) != EOF) { + if (c == '\n' || !isspace(c)) + break; + } + + while (c != EOF && c != '#' && c != '\n') { + if (alloc == length) { + alloc *= 2; + if ((new = realloc(string, alloc)) == NULL) + report("%m"); + string = new; + } + string[length++] = c; + c = input_getc_plain(); + } + if (c == '#') { + while ((c = input_getc_plain()) != EOF && c != '\n') + ; + } + if (c == EOF) + report("EOF in macro definition"); + + LIST_FOREACH(m, ¯os, link) + if (strcmp(m->name, varname) == 0) + break; + + if (m == NULL) { + if ((m = malloc(sizeof(*m))) == NULL) + report("%m"); + if ((m->name = malloc(strlen(varname) + 1)) == NULL) { + free(m); + report("%m"); + } + strcpy(m->name, varname); + m->perm = 0; + LIST_INSERT_HEAD(¯os, m, link); + + m->value = string; + m->length = length; + } else { + if (t == TOK_ASSIGN) { + free(m->value); + m->value = string; + m->length = length; + } else + free(string); + } + + token = TOK_EOL; + + ERRPOP(); +} + +/* + * Free all macros + */ +static void +macro_free_all(void) +{ + static struct macro *m, *m1; + + m = LIST_FIRST(¯os); + while (m != NULL) { + m1 = LIST_NEXT(m, link); + if (!m->perm) { + free(m->name); + free(m->value); + LIST_REMOVE(m, link); + free(m); + } + m = m1; + } +} + +/* + * Parse an include directive and switch to the new file + */ +static void +parse_include(void) +{ + int sysdir = 0; + char fname[_POSIX2_LINE_MAX]; + + if (gettoken() == '<') { + sysdir = 1; + if (gettoken() != TOK_STR) + report("expecting filename after in .include"); + } else if (token != TOK_STR) + report("expecting filename after in .include"); + + strcpy(fname, strval); + if (sysdir && gettoken() != '>') + report("expecting '>'"); + gettoken(); + if (input_open_file(fname, sysdir) == -1) + report("%s: %m", fname); +} + +/* + * Parse the configuration file + */ +static void +parse_file(const struct lmodule *mod) +{ + char varname[_POSIX2_LINE_MAX]; + + while (gettoken() != TOK_EOF) { + if (token == TOK_EOL) + /* empty line */ + continue; + if (token == '%') { + gettoken(); + parse_section(mod); + } else if (token == '.') { + if (gettoken() != TOK_STR) + report("keyword expected after '.'"); + if (strcmp(strval, "include") == 0) + parse_include(); + else + report("unknown keyword '%s'", strval); + } else if (token == TOK_STR) { + strcpy(varname, strval); + if (gettoken() == TOK_ASSIGN || token == TOK_QASSIGN) + parse_define(varname); + else + parse_assign(varname); + } + if (token != TOK_EOL) + report("eol expected"); + } +} + +/* + * Do rollback on errors + */ +static void +do_rollback(void) +{ + struct assign *tp; + struct snmp_node *node; + + while ((tp = TAILQ_LAST(&assigns, assigns)) != NULL) { + TAILQ_REMOVE(&assigns, tp, link); + for (node = tree; node < &tree[tree_size]; node++) + if (node->name == tp->node_name) { + snmp_ctx->scratch = &tp->scratch; + (void)(*node->op)(snmp_ctx, &tp->value, + node->oid.len, node->index, + SNMP_OP_ROLLBACK); + break; + } + if (node == &tree[tree_size]) + syslog(LOG_ERR, "failed to find node for " + "rollback"); + snmp_value_free(&tp->value); + free(tp); + } +} + +/* + * Do commit + */ +static void +do_commit(void) +{ + struct assign *tp; + struct snmp_node *node; + + while ((tp = TAILQ_FIRST(&assigns)) != NULL) { + TAILQ_REMOVE(&assigns, tp, link); + for (node = tree; node < &tree[tree_size]; node++) + if (node->name == tp->node_name) { + snmp_ctx->scratch = &tp->scratch; + (void)(*node->op)(snmp_ctx, &tp->value, + node->oid.len, node->index, SNMP_OP_COMMIT); + break; + } + if (node == &tree[tree_size]) + syslog(LOG_ERR, "failed to find node for commit"); + snmp_value_free(&tp->value); + free(tp); + } +} + +/* + * Read the configuration file. Handle the entire file as one transaction. + * + * If lodmod is NULL, the sections for 'snmpd' and all loaded modules are + * executed. If it is not NULL, only the sections for that module are handled. + */ +int +read_config(const char *fname, struct lmodule *lodmod) +{ + int err; + char objbuf[ASN_OIDSTRLEN]; + char idxbuf[ASN_OIDSTRLEN]; + + ignore = 0; + + input_push = 0; + + if (ERRPUSH()) + return (-1); + if (input_open_file(fname, 0) == -1) { + syslog(LOG_ERR, "%s: %m", fname); + return (-1); + } + ERRPOP(); + community = COMM_INITIALIZE; + + if ((snmp_ctx = snmp_init_context()) == NULL) { + input_close_all(); + syslog(LOG_ERR, "%m"); + return (-1); + } + + if (ERRPUSH()) { + do_rollback(); + input_close_all(); + macro_free_all(); + free(snmp_ctx); + return (-1); + } + parse_file(lodmod); + ERRPOP(); + + if ((err = snmp_dep_commit(snmp_ctx)) != SNMP_ERR_NOERROR) { + syslog(LOG_ERR, "init dep failed: %u %s %s", err, + asn_oid2str_r(&snmp_ctx->dep->obj, objbuf), + asn_oid2str_r(&snmp_ctx->dep->idx, idxbuf)); + snmp_dep_rollback(snmp_ctx); + do_rollback(); + input_close_all(); + macro_free_all(); + free(snmp_ctx); + return (-1); + } + + do_commit(); + snmp_dep_finish(snmp_ctx); + + macro_free_all(); + + free(snmp_ctx); + + return (0); +} + +/* + * Define a permanent macro + */ +int +define_macro(const char *name, const char *value) +{ + struct macro *m; + + if ((m = malloc(sizeof(*m))) == NULL) + return (-1); + if ((m->name = malloc(strlen(name) + 1)) == NULL) { + free(m); + return (-1); + } + strcpy(m->name, name); + if ((m->value = malloc(strlen(value) + 1)) == NULL) { + free(m->name); + free(m); + return (-1); + } + strcpy(m->value, value); + m->length = strlen(value); + m->perm = 1; + LIST_INSERT_HEAD(¯os, m, link); + return (0); +} Property changes on: vendor/bsnmp/1.13/snmpd/config.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/export.c =================================================================== --- vendor/bsnmp/1.13/snmpd/export.c (nonexistent) +++ vendor/bsnmp/1.13/snmpd/export.c (revision 336778) @@ -0,0 +1,404 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmpd/export.c,v 1.8 2006/02/14 09:04:20 brandt_h Exp $ + * + * Support functions for modules. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "snmpmod.h" +#include "snmpd.h" +#include "tree.h" + +/* + * Support functions + */ + +/* + * This is user for SET of string variables. If 'req' is not -1 then + * the arguments is checked to be of that length. The old value is saved + * in scratch->ptr1 and the new value is allocated and copied. + * If there is an old values it must have been allocated by malloc. + */ +int +string_save(struct snmp_value *value, struct snmp_context *ctx, + ssize_t req_size, u_char **valp) +{ + if (req_size != -1 && value->v.octetstring.len != (u_long)req_size) + return (SNMP_ERR_BADVALUE); + + ctx->scratch->ptr1 = *valp; + + if ((*valp = malloc(value->v.octetstring.len + 1)) == NULL) { + *valp = ctx->scratch->ptr1; + return (SNMP_ERR_RES_UNAVAIL); + } + + memcpy(*valp, value->v.octetstring.octets, value->v.octetstring.len); + (*valp)[value->v.octetstring.len] = '\0'; + + return (0); +} + +/* + * Commit a string. This is easy - free the old value. + */ +void +string_commit(struct snmp_context *ctx) +{ + free(ctx->scratch->ptr1); +} + +/* + * Rollback a string - free new value and copy back old one. + */ +void +string_rollback(struct snmp_context *ctx, u_char **valp) +{ + free(*valp); + *valp = ctx->scratch->ptr1; +} + +/* + * ROLLBACK or COMMIT fails because instance has disappeared. Free string. + */ +void +string_free(struct snmp_context *ctx) +{ + free(ctx->scratch->ptr1); +} + +/* + * Get a string value for a response packet + */ +int +string_get(struct snmp_value *value, const u_char *ptr, ssize_t len) +{ + if (ptr == NULL) { + value->v.octetstring.len = 0; + value->v.octetstring.octets = NULL; + return (SNMP_ERR_NOERROR); + } + if (len == -1) + len = strlen(ptr); + if ((value->v.octetstring.octets = malloc((size_t)len)) == NULL) { + value->v.octetstring.len = 0; + return (SNMP_ERR_RES_UNAVAIL); + } + value->v.octetstring.len = (u_long)len; + memcpy(value->v.octetstring.octets, ptr, (size_t)len); + return (SNMP_ERR_NOERROR); +} + +/* + * Get a string value for a response packet but cut it if it is too long. + */ +int +string_get_max(struct snmp_value *value, const u_char *ptr, ssize_t len, + size_t maxlen) +{ + + if (ptr == NULL) { + value->v.octetstring.len = 0; + value->v.octetstring.octets = NULL; + return (SNMP_ERR_NOERROR); + } + if (len == -1) + len = strlen(ptr); + if ((size_t)len > maxlen) + len = maxlen; + if ((value->v.octetstring.octets = malloc((size_t)len)) == NULL) { + value->v.octetstring.len = 0; + return (SNMP_ERR_RES_UNAVAIL); + } + value->v.octetstring.len = (u_long)len; + memcpy(value->v.octetstring.octets, ptr, (size_t)len); + return (SNMP_ERR_NOERROR); +} + +/* + * Support for IPADDRESS + * + * Save the old IP address in scratch->int1 and set the new one. + */ +int +ip_save(struct snmp_value *value, struct snmp_context *ctx, u_char *valp) +{ + ctx->scratch->int1 = (valp[0] << 24) | (valp[1] << 16) | (valp[2] << 8) + | valp[3]; + + valp[0] = value->v.ipaddress[0]; + valp[1] = value->v.ipaddress[1]; + valp[2] = value->v.ipaddress[2]; + valp[3] = value->v.ipaddress[3]; + + return (0); +} + +/* + * Rollback the address by copying back the old one + */ +void +ip_rollback(struct snmp_context *ctx, u_char *valp) +{ + valp[0] = ctx->scratch->int1 >> 24; + valp[1] = ctx->scratch->int1 >> 16; + valp[2] = ctx->scratch->int1 >> 8; + valp[3] = ctx->scratch->int1; +} + +/* + * Nothing to do for commit + */ +void +ip_commit(struct snmp_context *ctx __unused) +{ +} + +/* + * Retrieve an IP address + */ +int +ip_get(struct snmp_value *value, u_char *valp) +{ + value->v.ipaddress[0] = valp[0]; + value->v.ipaddress[1] = valp[1]; + value->v.ipaddress[2] = valp[2]; + value->v.ipaddress[3] = valp[3]; + + return (SNMP_ERR_NOERROR); +} + +/* + * Object ID support + * + * Save the old value in a fresh allocated oid pointed to by scratch->ptr1. + */ +int +oid_save(struct snmp_value *value, struct snmp_context *ctx, + struct asn_oid *oid) +{ + if ((ctx->scratch->ptr1 = malloc(sizeof(struct asn_oid))) == NULL) + return (SNMP_ERR_RES_UNAVAIL); + *(struct asn_oid *)ctx->scratch->ptr1 = *oid; + *oid = value->v.oid; + + return (0); +} + +void +oid_rollback(struct snmp_context *ctx, struct asn_oid *oid) +{ + *oid = *(struct asn_oid *)ctx->scratch->ptr1; + free(ctx->scratch->ptr1); +} + +void +oid_commit(struct snmp_context *ctx) +{ + free(ctx->scratch->ptr1); +} + +int +oid_get(struct snmp_value *value, const struct asn_oid *oid) +{ + value->v.oid = *oid; + return (SNMP_ERR_NOERROR); +} + +/* + * Decode an index + */ +int +index_decode(const struct asn_oid *oid, u_int sub, u_int code, ...) +{ + va_list ap; + u_int index_count; + void *octs[10]; + u_int nocts; + u_int idx; + + va_start(ap, code); + index_count = SNMP_INDEX_COUNT(code); + nocts = 0; + + for (idx = 0; idx < index_count; idx++) { + switch (SNMP_INDEX(code, idx)) { + + case SNMP_SYNTAX_NULL: + break; + + case SNMP_SYNTAX_INTEGER: + if (sub == oid->len) + goto err; + *va_arg(ap, int32_t *) = oid->subs[sub++]; + break; + + case SNMP_SYNTAX_COUNTER64: + if (sub == oid->len) + goto err; + *va_arg(ap, u_int64_t *) = oid->subs[sub++]; + break; + + case SNMP_SYNTAX_OCTETSTRING: + { + u_char **cval; + size_t *sval; + u_int i; + + /* only variable size supported */ + if (sub == oid->len) + goto err; + cval = va_arg(ap, u_char **); + sval = va_arg(ap, size_t *); + *sval = oid->subs[sub++]; + if (sub + *sval > oid->len) + goto err; + if ((*cval = malloc(*sval)) == NULL) { + syslog(LOG_ERR, "%s: %m", __func__); + goto err; + } + octs[nocts++] = *cval; + for (i = 0; i < *sval; i++) { + if (oid->subs[sub] > 0xff) + goto err; + (*cval)[i] = oid->subs[sub++]; + } + break; + } + + case SNMP_SYNTAX_OID: + { + struct asn_oid *aval; + u_int i; + + if (sub == oid->len) + goto err; + aval = va_arg(ap, struct asn_oid *); + aval->len = oid->subs[sub++]; + if (aval->len > ASN_MAXOIDLEN) + goto err; + for (i = 0; i < aval->len; i++) + aval->subs[i] = oid->subs[sub++]; + break; + } + + case SNMP_SYNTAX_IPADDRESS: + { + u_int8_t *pval; + u_int i; + + if (sub + 4 > oid->len) + goto err; + pval = va_arg(ap, u_int8_t *); + for (i = 0; i < 4; i++) { + if (oid->subs[sub] > 0xff) + goto err; + pval[i] = oid->subs[sub++]; + } + break; + } + + case SNMP_SYNTAX_COUNTER: + case SNMP_SYNTAX_GAUGE: + case SNMP_SYNTAX_TIMETICKS: + if (sub == oid->len) + goto err; + if (oid->subs[sub] > 0xffffffff) + goto err; + *va_arg(ap, u_int32_t *) = oid->subs[sub++]; + break; + } + } + + va_end(ap); + return (0); + + err: + va_end(ap); + while(nocts > 0) + free(octs[--nocts]); + return (-1); +} + +/* + * Compare the index part of an OID and an index. + */ +int +index_compare_off(const struct asn_oid *oid, u_int sub, + const struct asn_oid *idx, u_int off) +{ + u_int i; + + for (i = off; i < idx->len && i < oid->len - sub; i++) { + if (oid->subs[sub + i] < idx->subs[i]) + return (-1); + if (oid->subs[sub + i] > idx->subs[i]) + return (+1); + } + if (oid->len - sub < idx->len) + return (-1); + if (oid->len - sub > idx->len) + return (+1); + + return (0); +} + +int +index_compare(const struct asn_oid *oid, u_int sub, const struct asn_oid *idx) +{ + return (index_compare_off(oid, sub, idx, 0)); +} + +/* + * Append an index to an oid + */ +void +index_append_off(struct asn_oid *var, u_int sub, const struct asn_oid *idx, + u_int off) +{ + u_int i; + + var->len = sub + idx->len; + for (i = off; i < idx->len; i++) + var->subs[sub + i] = idx->subs[i]; +} +void +index_append(struct asn_oid *var, u_int sub, const struct asn_oid *idx) +{ + index_append_off(var, sub, idx, 0); +} + Property changes on: vendor/bsnmp/1.13/snmpd/export.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/main.c =================================================================== --- vendor/bsnmp/1.13/snmpd/main.c (nonexistent) +++ vendor/bsnmp/1.13/snmpd/main.c (revision 336778) @@ -0,0 +1,3111 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Copyright (c) 2010 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by Shteryana Sotirova Shopova + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmpd/main.c,v 1.100 2006/02/14 09:04:20 brandt_h Exp $ + * + * SNMPd main stuff. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_TCPWRAPPERS +#include +#include +#endif + +#include "support.h" +#include "snmpmod.h" +#include "snmpd.h" +#include "tree.h" +#include "oid.h" + +#define PATH_PID "/var/run/%s.pid" +#define PATH_CONFIG "/etc/%s.config" +#define PATH_ENGINE "/var/%s.engine" + +uint64_t this_tick; /* start of processing of current packet (absolute) */ +uint64_t start_tick; /* start of processing */ + +struct systemg systemg = { + NULL, + { 8, { 1, 3, 6, 1, 4, 1, 1115, 7352 }}, + NULL, NULL, NULL, + 64 + 8 + 4, + 0 +}; +struct debug debug = { + 0, /* dump_pdus */ + LOG_DEBUG, /* log_pri */ + 0, /* evdebug */ +}; + +struct snmpd snmpd = { + 2048, /* txbuf */ + 2048, /* rxbuf */ + 0, /* comm_dis */ + 0, /* auth_traps */ + {0, 0, 0, 0}, /* trap1addr */ + VERS_ENABLE_ALL,/* version_enable */ +}; +struct snmpd_stats snmpd_stats; + +struct snmpd_usmstat snmpd_usmstats; + +/* snmpEngine */ +struct snmp_engine snmpd_engine; + +/* snmpSerialNo */ +int32_t snmp_serial_no; + +struct snmpd_target_stats snmpd_target_stats; + +/* search path for config files */ +const char *syspath = PATH_SYSCONFIG; + +/* list of all loaded modules */ +struct lmodules lmodules = TAILQ_HEAD_INITIALIZER(lmodules); + +/* list of loaded modules during start-up in the order they were loaded */ +static struct lmodules modules_start = TAILQ_HEAD_INITIALIZER(modules_start); + +/* list of all known communities */ +struct community_list community_list = TAILQ_HEAD_INITIALIZER(community_list); + +/* list of all known USM users */ +static struct usm_userlist usm_userlist = SLIST_HEAD_INITIALIZER(usm_userlist); + +/* A list of all VACM users configured, including v1, v2c and v3 */ +static struct vacm_userlist vacm_userlist = + SLIST_HEAD_INITIALIZER(vacm_userlist); + +/* A list of all VACM groups */ +static struct vacm_grouplist vacm_grouplist = + SLIST_HEAD_INITIALIZER(vacm_grouplist); + +static struct vacm_group vacm_default_group = { + .groupname = "", +}; + +/* The list of configured access entries */ +static struct vacm_accesslist vacm_accesslist = + TAILQ_HEAD_INITIALIZER(vacm_accesslist); + +/* The list of configured views */ +static struct vacm_viewlist vacm_viewlist = + SLIST_HEAD_INITIALIZER(vacm_viewlist); + +/* The list of configured contexts */ +static struct vacm_contextlist vacm_contextlist = + SLIST_HEAD_INITIALIZER(vacm_contextlist); + +/* list of all installed object resources */ +struct objres_list objres_list = TAILQ_HEAD_INITIALIZER(objres_list); + +/* community value generator */ +static u_int next_community_index = 1; + +/* list of all known ranges */ +struct idrange_list idrange_list = TAILQ_HEAD_INITIALIZER(idrange_list); + +/* identifier generator */ +u_int next_idrange = 1; + +/* list of all current timers */ +struct timer_list timer_list = LIST_HEAD_INITIALIZER(timer_list); + +/* list of file descriptors */ +struct fdesc_list fdesc_list = LIST_HEAD_INITIALIZER(fdesc_list); + +/* program arguments */ +static char **progargs; +static int nprogargs; + +/* current community */ +u_int community; +static struct community *comm; + +/* current USM user */ +struct usm_user *usm_user; + +/* file names */ +static char config_file[MAXPATHLEN + 1]; +static char pid_file[MAXPATHLEN + 1]; +char engine_file[MAXPATHLEN + 1]; + +#ifndef USE_LIBBEGEMOT +/* event context */ +static evContext evctx; +#endif + +/* signal mask */ +static sigset_t blocked_sigs; + +/* signal handling */ +static int work; +#define WORK_DOINFO 0x0001 +#define WORK_RECONFIG 0x0002 + +/* oids */ +static const struct asn_oid + oid_snmpMIB = OIDX_snmpMIB, + oid_begemotSnmpd = OIDX_begemotSnmpd, + oid_coldStart = OIDX_coldStart, + oid_authenticationFailure = OIDX_authenticationFailure; + +const struct asn_oid oid_zeroDotZero = { 2, { 0, 0 }}; + +const struct asn_oid oid_usmUnknownEngineIDs = + { 11, { 1, 3, 6, 1, 6, 3, 15, 1, 1, 4, 0}}; + +const struct asn_oid oid_usmNotInTimeWindows = + { 11, { 1, 3, 6, 1, 6, 3, 15, 1, 1, 2, 0}}; + +/* request id generator for traps */ +u_int trap_reqid; + +/* help text */ +static const char usgtxt[] = "\ +Begemot simple SNMP daemon. Copyright (c) 2001-2002 Fraunhofer Institute for\n\ +Open Communication Systems (FhG Fokus). All rights reserved.\n\ +Copyright (c) 2010 The FreeBSD Foundation. All rights reserved.\n\ +usage: snmpd [-dh] [-c file] [-D options] [-e file] [-I path]\n\ + [-l prefix] [-m variable=value] [-p file]\n\ +options:\n\ + -d don't daemonize\n\ + -h print this info\n\ + -c file specify configuration file\n\ + -D options debugging options\n\ + -e file specify engine id file\n\ + -I path system include path\n\ + -l prefix default basename for pid and config file\n\ + -m var=val define variable\n\ + -p file specify pid file\n\ +"; + +/* hosts_access(3) request */ +#ifdef USE_TCPWRAPPERS +static struct request_info req; +#endif + +/* transports */ +extern const struct transport_def udp_trans; +extern const struct transport_def lsock_trans; + +struct transport_list transport_list = TAILQ_HEAD_INITIALIZER(transport_list); + +/* forward declarations */ +static void snmp_printf_func(const char *fmt, ...); +static void snmp_error_func(const char *err, ...); +static void snmp_debug_func(const char *err, ...); +static void asn_error_func(const struct asn_buf *b, const char *err, ...); + +/* + * Allocate rx/tx buffer. We allocate one byte more for rx. + */ +void * +buf_alloc(int tx) +{ + void *buf; + + if ((buf = malloc(tx ? snmpd.txbuf : snmpd.rxbuf)) == NULL) { + syslog(LOG_CRIT, "cannot allocate buffer"); + if (tx) + snmpd_stats.noTxbuf++; + else + snmpd_stats.noRxbuf++; + return (NULL); + } + return (buf); +} + +/* + * Return the buffer size. + */ +size_t +buf_size(int tx) +{ + return (tx ? snmpd.txbuf : snmpd.rxbuf); +} + +/* + * Prepare a PDU for output + */ +void +snmp_output(struct snmp_pdu *pdu, u_char *sndbuf, size_t *sndlen, + const char *dest) +{ + struct asn_buf resp_b; + enum snmp_code code; + + resp_b.asn_ptr = sndbuf; + resp_b.asn_len = snmpd.txbuf; + + if ((code = snmp_pdu_encode(pdu, &resp_b)) != SNMP_CODE_OK) { + syslog(LOG_ERR, "cannot encode message (code=%d)", code); + abort(); + } + if (debug.dump_pdus) { + snmp_printf("%s <- ", dest); + snmp_pdu_dump(pdu); + } + *sndlen = (size_t)(resp_b.asn_ptr - sndbuf); +} + +/* + * Check USM PDU header credentials against local SNMP Engine & users. + */ +static enum snmp_code +snmp_pdu_auth_user(struct snmp_pdu *pdu) +{ + usm_user = NULL; + + /* un-authenticated snmpEngineId discovery */ + if (pdu->engine.engine_len == 0 && strlen(pdu->user.sec_name) == 0) { + pdu->engine.engine_len = snmpd_engine.engine_len; + memcpy(pdu->engine.engine_id, snmpd_engine.engine_id, + snmpd_engine.engine_len); + update_snmpd_engine_time(); + pdu->engine.engine_boots = snmpd_engine.engine_boots; + pdu->engine.engine_time = snmpd_engine.engine_time; + pdu->flags |= SNMP_MSG_AUTODISCOVER; + return (SNMP_CODE_OK); + } + + if ((usm_user = usm_find_user(pdu->engine.engine_id, + pdu->engine.engine_len, pdu->user.sec_name)) == NULL || + usm_user->status != 1 /* active */) + return (SNMP_CODE_BADUSER); + + if (usm_user->user_engine_len != snmpd_engine.engine_len || + memcmp(usm_user->user_engine_id, snmpd_engine.engine_id, + snmpd_engine.engine_len) != 0) + return (SNMP_CODE_BADENGINE); + + pdu->user.priv_proto = usm_user->suser.priv_proto; + memcpy(pdu->user.priv_key, usm_user->suser.priv_key, + sizeof(pdu->user.priv_key)); + + /* authenticated snmpEngineId discovery */ + if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) { + update_snmpd_engine_time(); + pdu->user.auth_proto = usm_user->suser.auth_proto; + memcpy(pdu->user.auth_key, usm_user->suser.auth_key, + sizeof(pdu->user.auth_key)); + + if (pdu->engine.engine_boots == 0 && + pdu->engine.engine_time == 0) { + update_snmpd_engine_time(); + pdu->flags |= SNMP_MSG_AUTODISCOVER; + return (SNMP_CODE_OK); + } + + if (pdu->engine.engine_boots != snmpd_engine.engine_boots || + abs(pdu->engine.engine_time - snmpd_engine.engine_time) > + SNMP_TIME_WINDOW) + return (SNMP_CODE_NOTINTIME); + } + + if (((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0 && + (pdu->flags & SNMP_MSG_AUTH_FLAG) == 0) || + ((pdu->flags & SNMP_MSG_AUTH_FLAG) == 0 && + usm_user->suser.auth_proto != SNMP_AUTH_NOAUTH) || + ((pdu->flags & SNMP_MSG_PRIV_FLAG) == 0 && + usm_user->suser.priv_proto != SNMP_PRIV_NOPRIV)) + return (SNMP_CODE_BADSECLEVEL); + + return (SNMP_CODE_OK); +} + +/* + * Check whether access to each of var bindings in the PDU is allowed based + * on the user credentials against the configured User groups & VACM views. + */ +enum snmp_code +snmp_pdu_auth_access(struct snmp_pdu *pdu, int32_t *ip) +{ + const char *uname; + int32_t suboid, smodel; + uint32_t i; + struct vacm_user *vuser; + struct vacm_access *acl; + struct vacm_context *vacmctx; + struct vacm_view *view; + + /* + * At least a default context exists if the snmpd_vacm(3) module is + * running. + */ + if (SLIST_EMPTY(&vacm_contextlist) || + (pdu->flags & SNMP_MSG_AUTODISCOVER) != 0) + return (SNMP_CODE_OK); + + switch (pdu->version) { + case SNMP_V1: + if ((uname = comm_string(community)) == NULL) + return (SNMP_CODE_FAILED); + smodel = SNMP_SECMODEL_SNMPv1; + break; + + case SNMP_V2c: + if ((uname = comm_string(community)) == NULL) + return (SNMP_CODE_FAILED); + smodel = SNMP_SECMODEL_SNMPv2c; + break; + + case SNMP_V3: + uname = pdu->user.sec_name; + if ((smodel = pdu->security_model) != SNMP_SECMODEL_USM) + return (SNMP_CODE_FAILED); + /* Compare the PDU context engine id against the agent's */ + if (pdu->context_engine_len != snmpd_engine.engine_len || + memcmp(pdu->context_engine, snmpd_engine.engine_id, + snmpd_engine.engine_len) != 0) + return (SNMP_CODE_FAILED); + break; + + default: + abort(); + } + + SLIST_FOREACH(vuser, &vacm_userlist, vvu) + if (strcmp(uname, vuser->secname) == 0 && + vuser->sec_model == smodel) + break; + + if (vuser == NULL || vuser->group == NULL) + return (SNMP_CODE_FAILED); + + /* XXX: shteryana - recheck */ + TAILQ_FOREACH_REVERSE(acl, &vacm_accesslist, vacm_accesslist, vva) { + if (acl->group != vuser->group) + continue; + SLIST_FOREACH(vacmctx, &vacm_contextlist, vcl) + if (memcmp(vacmctx->ctxname, acl->ctx_prefix, + acl->ctx_match) == 0) + goto match; + } + + return (SNMP_CODE_FAILED); + +match: + + switch (pdu->type) { + case SNMP_PDU_GET: + case SNMP_PDU_GETNEXT: + case SNMP_PDU_GETBULK: + if ((view = acl->read_view) == NULL) + return (SNMP_CODE_FAILED); + break; + + case SNMP_PDU_SET: + if ((view = acl->write_view) == NULL) + return (SNMP_CODE_FAILED); + break; + + case SNMP_PDU_TRAP: + case SNMP_PDU_INFORM: + case SNMP_PDU_TRAP2: + case SNMP_PDU_REPORT: + if ((view = acl->notify_view) == NULL) + return (SNMP_CODE_FAILED); + break; + case SNMP_PDU_RESPONSE: + /* NOTREACHED */ + return (SNMP_CODE_FAILED); + default: + abort(); + } + + for (i = 0; i < pdu->nbindings; i++) { + /* XXX - view->mask*/ + suboid = asn_is_suboid(&view->subtree, &pdu->bindings[i].var); + if ((!suboid && !view->exclude) || (suboid && view->exclude)) { + *ip = i + 1; + return (SNMP_CODE_FAILED); + } + } + + return (SNMP_CODE_OK); +} + +/* + * SNMP input. Start: decode the PDU, find the user or community. + */ +enum snmpd_input_err +snmp_input_start(const u_char *buf, size_t len, const char *source, + struct snmp_pdu *pdu, int32_t *ip, size_t *pdulen) +{ + struct asn_buf b; + enum snmp_code code; + enum snmpd_input_err ret; + int sret; + + /* update uptime */ + this_tick = get_ticks(); + + b.asn_cptr = buf; + b.asn_len = len; + + ret = SNMPD_INPUT_OK; + + /* look whether we have enough bytes for the entire PDU. */ + switch (sret = snmp_pdu_snoop(&b)) { + + case 0: + return (SNMPD_INPUT_TRUNC); + + case -1: + snmpd_stats.inASNParseErrs++; + return (SNMPD_INPUT_FAILED); + } + b.asn_len = *pdulen = (size_t)sret; + + memset(pdu, 0, sizeof(*pdu)); + if ((code = snmp_pdu_decode_header(&b, pdu)) != SNMP_CODE_OK) + goto decoded; + + if (pdu->version == SNMP_V3) { + if (pdu->security_model != SNMP_SECMODEL_USM) { + code = SNMP_CODE_FAILED; + goto decoded; + } + if ((code = snmp_pdu_auth_user(pdu)) != SNMP_CODE_OK) + goto decoded; + if ((code = snmp_pdu_decode_secmode(&b, pdu)) != SNMP_CODE_OK) + goto decoded; + } + code = snmp_pdu_decode_scoped(&b, pdu, ip); + +decoded: + snmpd_stats.inPkts++; + + switch (code) { + + case SNMP_CODE_FAILED: + snmpd_stats.inASNParseErrs++; + return (SNMPD_INPUT_FAILED); + + case SNMP_CODE_BADVERS: + bad_vers: + snmpd_stats.inBadVersions++; + return (SNMPD_INPUT_FAILED); + + case SNMP_CODE_BADLEN: + if (pdu->type == SNMP_OP_SET) + ret = SNMPD_INPUT_VALBADLEN; + break; + + case SNMP_CODE_OORANGE: + if (pdu->type == SNMP_OP_SET) + ret = SNMPD_INPUT_VALRANGE; + break; + + case SNMP_CODE_BADENC: + if (pdu->type == SNMP_OP_SET) + ret = SNMPD_INPUT_VALBADENC; + break; + + case SNMP_CODE_BADSECLEVEL: + snmpd_usmstats.unsupported_seclevels++; + return (SNMPD_INPUT_FAILED); + + case SNMP_CODE_NOTINTIME: + snmpd_usmstats.not_in_time_windows++; + return (SNMPD_INPUT_FAILED); + + case SNMP_CODE_BADUSER: + snmpd_usmstats.unknown_users++; + return (SNMPD_INPUT_FAILED); + + case SNMP_CODE_BADENGINE: + snmpd_usmstats.unknown_engine_ids++; + return (SNMPD_INPUT_FAILED); + + case SNMP_CODE_BADDIGEST: + snmpd_usmstats.wrong_digests++; + return (SNMPD_INPUT_FAILED); + + case SNMP_CODE_EDECRYPT: + snmpd_usmstats.decrypt_errors++; + return (SNMPD_INPUT_FAILED); + + case SNMP_CODE_OK: + switch (pdu->version) { + + case SNMP_V1: + if (!(snmpd.version_enable & VERS_ENABLE_V1)) + goto bad_vers; + break; + + case SNMP_V2c: + if (!(snmpd.version_enable & VERS_ENABLE_V2C)) + goto bad_vers; + break; + + case SNMP_V3: + if (!(snmpd.version_enable & VERS_ENABLE_V3)) + goto bad_vers; + break; + + case SNMP_Verr: + goto bad_vers; + } + break; + } + + if (debug.dump_pdus) { + snmp_printf("%s -> ", source); + snmp_pdu_dump(pdu); + } + + /* + * Look, whether we know the community or user + */ + + if (pdu->version != SNMP_V3) { + TAILQ_FOREACH(comm, &community_list, link) + if (comm->string != NULL && + strcmp(comm->string, pdu->community) == 0) + break; + + if (comm == NULL) { + snmpd_stats.inBadCommunityNames++; + snmp_pdu_free(pdu); + if (snmpd.auth_traps) + snmp_send_trap(&oid_authenticationFailure, + (struct snmp_value *)NULL); + ret = SNMPD_INPUT_BAD_COMM; + } else + community = comm->value; + } else if (pdu->nbindings == 0) { + /* RFC 3414 - snmpEngineID Discovery */ + if (strlen(pdu->user.sec_name) == 0) { + asn_append_oid(&(pdu->bindings[pdu->nbindings++].var), + &oid_usmUnknownEngineIDs); + pdu->context_engine_len = snmpd_engine.engine_len; + memcpy(pdu->context_engine, snmpd_engine.engine_id, + snmpd_engine.engine_len); + } else if (pdu->engine.engine_boots == 0 && + pdu->engine.engine_time == 0) { + asn_append_oid(&(pdu->bindings[pdu->nbindings++].var), + &oid_usmNotInTimeWindows); + update_snmpd_engine_time(); + pdu->engine.engine_boots = snmpd_engine.engine_boots; + pdu->engine.engine_time = snmpd_engine.engine_time; + } + } else if (usm_user->suser.auth_proto != SNMP_AUTH_NOAUTH && + (pdu->engine.engine_boots == 0 || pdu->engine.engine_time == 0)) { + snmpd_usmstats.not_in_time_windows++; + ret = SNMPD_INPUT_FAILED; + } + + if ((code = snmp_pdu_auth_access(pdu, ip)) != SNMP_CODE_OK) + ret = SNMPD_INPUT_FAILED; + + return (ret); +} + +/* + * Will return only _OK or _FAILED + */ +enum snmpd_input_err +snmp_input_finish(struct snmp_pdu *pdu, const u_char *rcvbuf, size_t rcvlen, + u_char *sndbuf, size_t *sndlen, const char *source, + enum snmpd_input_err ierr, int32_t ivar, void *data) +{ + struct snmp_pdu resp; + struct asn_buf resp_b, pdu_b; + enum snmp_ret ret; + + resp_b.asn_ptr = sndbuf; + resp_b.asn_len = snmpd.txbuf; + + pdu_b.asn_cptr = rcvbuf; + pdu_b.asn_len = rcvlen; + + if (ierr != SNMPD_INPUT_OK) { + /* error decoding the input of a SET */ + if (pdu->version == SNMP_V1) + pdu->error_status = SNMP_ERR_BADVALUE; + else if (ierr == SNMPD_INPUT_VALBADLEN) + pdu->error_status = SNMP_ERR_WRONG_LENGTH; + else if (ierr == SNMPD_INPUT_VALRANGE) + pdu->error_status = SNMP_ERR_WRONG_VALUE; + else + pdu->error_status = SNMP_ERR_WRONG_ENCODING; + + pdu->error_index = ivar; + + if (snmp_make_errresp(pdu, &pdu_b, &resp_b) == SNMP_RET_IGN) { + syslog(LOG_WARNING, "could not encode error response"); + snmpd_stats.silentDrops++; + return (SNMPD_INPUT_FAILED); + } + + if (debug.dump_pdus) { + snmp_printf("%s <- ", source); + snmp_pdu_dump(pdu); + } + *sndlen = (size_t)(resp_b.asn_ptr - sndbuf); + return (SNMPD_INPUT_OK); + } + + switch (pdu->type) { + + case SNMP_PDU_GET: + ret = snmp_get(pdu, &resp_b, &resp, data); + break; + + case SNMP_PDU_GETNEXT: + ret = snmp_getnext(pdu, &resp_b, &resp, data); + break; + + case SNMP_PDU_SET: + ret = snmp_set(pdu, &resp_b, &resp, data); + break; + + case SNMP_PDU_GETBULK: + ret = snmp_getbulk(pdu, &resp_b, &resp, data); + break; + + default: + ret = SNMP_RET_IGN; + break; + } + + switch (ret) { + + case SNMP_RET_OK: + /* normal return - send a response */ + if (debug.dump_pdus) { + snmp_printf("%s <- ", source); + snmp_pdu_dump(&resp); + } + *sndlen = (size_t)(resp_b.asn_ptr - sndbuf); + snmp_pdu_free(&resp); + return (SNMPD_INPUT_OK); + + case SNMP_RET_IGN: + /* error - send nothing */ + snmpd_stats.silentDrops++; + return (SNMPD_INPUT_FAILED); + + case SNMP_RET_ERR: + /* error - send error response. The snmp routine has + * changed the error fields in the original message. */ + resp_b.asn_ptr = sndbuf; + resp_b.asn_len = snmpd.txbuf; + if (snmp_make_errresp(pdu, &pdu_b, &resp_b) == SNMP_RET_IGN) { + syslog(LOG_WARNING, "could not encode error response"); + snmpd_stats.silentDrops++; + return (SNMPD_INPUT_FAILED); + } else { + if (debug.dump_pdus) { + snmp_printf("%s <- ", source); + snmp_pdu_dump(pdu); + } + *sndlen = (size_t)(resp_b.asn_ptr - sndbuf); + return (SNMPD_INPUT_OK); + } + } + abort(); +} + +/* + * Insert a port into the right place in the transport's table of ports + */ +void +trans_insert_port(struct transport *t, struct tport *port) +{ + struct tport *p; + + TAILQ_FOREACH(p, &t->table, link) { + if (asn_compare_oid(&p->index, &port->index) > 0) { + TAILQ_INSERT_BEFORE(p, port, link); + return; + } + } + port->transport = t; + TAILQ_INSERT_TAIL(&t->table, port, link); +} + +/* + * Remove a port from a transport's list + */ +void +trans_remove_port(struct tport *port) +{ + + TAILQ_REMOVE(&port->transport->table, port, link); +} + +/* + * Find a port on a transport's list + */ +struct tport * +trans_find_port(struct transport *t, const struct asn_oid *idx, u_int sub) +{ + + return (FIND_OBJECT_OID(&t->table, idx, sub)); +} + +/* + * Find next port on a transport's list + */ +struct tport * +trans_next_port(struct transport *t, const struct asn_oid *idx, u_int sub) +{ + + return (NEXT_OBJECT_OID(&t->table, idx, sub)); +} + +/* + * Return first port + */ +struct tport * +trans_first_port(struct transport *t) +{ + + return (TAILQ_FIRST(&t->table)); +} + +/* + * Iterate through all ports until a function returns a 0. + */ +struct tport * +trans_iter_port(struct transport *t, int (*func)(struct tport *, intptr_t), + intptr_t arg) +{ + struct tport *p; + + TAILQ_FOREACH(p, &t->table, link) + if (func(p, arg) == 0) + return (p); + return (NULL); +} + +/* + * Register a transport + */ +int +trans_register(const struct transport_def *def, struct transport **pp) +{ + u_int i; + char or_descr[256]; + + if ((*pp = malloc(sizeof(**pp))) == NULL) + return (SNMP_ERR_GENERR); + + /* construct index */ + (*pp)->index.len = strlen(def->name) + 1; + (*pp)->index.subs[0] = strlen(def->name); + for (i = 0; i < (*pp)->index.subs[0]; i++) + (*pp)->index.subs[i + 1] = def->name[i]; + + (*pp)->vtab = def; + + if (FIND_OBJECT_OID(&transport_list, &(*pp)->index, 0) != NULL) { + free(*pp); + return (SNMP_ERR_INCONS_VALUE); + } + + /* register module */ + snprintf(or_descr, sizeof(or_descr), "%s transport mapping", def->name); + if (((*pp)->or_index = or_register(&def->id, or_descr, NULL)) == 0) { + free(*pp); + return (SNMP_ERR_GENERR); + } + + INSERT_OBJECT_OID((*pp), &transport_list); + + TAILQ_INIT(&(*pp)->table); + + return (SNMP_ERR_NOERROR); +} + +/* + * Unregister transport + */ +int +trans_unregister(struct transport *t) +{ + if (!TAILQ_EMPTY(&t->table)) + return (SNMP_ERR_INCONS_VALUE); + + or_unregister(t->or_index); + TAILQ_REMOVE(&transport_list, t, link); + + return (SNMP_ERR_NOERROR); +} + +/* + * File descriptor support + */ +#ifdef USE_LIBBEGEMOT +static void +input(int fd, int mask __unused, void *uap) +#else +static void +input(evContext ctx __unused, void *uap, int fd, int mask __unused) +#endif +{ + struct fdesc *f = uap; + + (*f->func)(fd, f->udata); +} + +void +fd_suspend(void *p) +{ + struct fdesc *f = p; + +#ifdef USE_LIBBEGEMOT + if (f->id >= 0) { + poll_unregister(f->id); + f->id = -1; + } +#else + if (evTestID(f->id)) { + (void)evDeselectFD(evctx, f->id); + evInitID(&f->id); + } +#endif +} + +int +fd_resume(void *p) +{ + struct fdesc *f = p; + int err; + +#ifdef USE_LIBBEGEMOT + if (f->id >= 0) + return (0); + if ((f->id = poll_register(f->fd, input, f, RPOLL_IN)) < 0) { + err = errno; + syslog(LOG_ERR, "select fd %d: %m", f->fd); + errno = err; + return (-1); + } +#else + if (evTestID(f->id)) + return (0); + if (evSelectFD(evctx, f->fd, EV_READ, input, f, &f->id)) { + err = errno; + syslog(LOG_ERR, "select fd %d: %m", f->fd); + errno = err; + return (-1); + } +#endif + return (0); +} + +void * +fd_select(int fd, void (*func)(int, void *), void *udata, struct lmodule *mod) +{ + struct fdesc *f; + int err; + + if ((f = malloc(sizeof(struct fdesc))) == NULL) { + err = errno; + syslog(LOG_ERR, "fd_select: %m"); + errno = err; + return (NULL); + } + f->fd = fd; + f->func = func; + f->udata = udata; + f->owner = mod; +#ifdef USE_LIBBEGEMOT + f->id = -1; +#else + evInitID(&f->id); +#endif + + if (fd_resume(f)) { + err = errno; + free(f); + errno = err; + return (NULL); + } + + LIST_INSERT_HEAD(&fdesc_list, f, link); + + return (f); +} + +void +fd_deselect(void *p) +{ + struct fdesc *f = p; + + LIST_REMOVE(f, link); + fd_suspend(f); + free(f); +} + +static void +fd_flush(struct lmodule *mod) +{ + struct fdesc *t, *t1; + + t = LIST_FIRST(&fdesc_list); + while (t != NULL) { + t1 = LIST_NEXT(t, link); + if (t->owner == mod) + fd_deselect(t); + t = t1; + } +} + +/* + * Consume a message from the input buffer + */ +static void +snmp_input_consume(struct port_input *pi) +{ + if (!pi->stream) { + /* always consume everything */ + pi->length = 0; + return; + } + if (pi->consumed >= pi->length) { + /* all bytes consumed */ + pi->length = 0; + return; + } + memmove(pi->buf, pi->buf + pi->consumed, pi->length - pi->consumed); + pi->length -= pi->consumed; +} + +/* + * Input from a socket + */ +int +snmpd_input(struct port_input *pi, struct tport *tport) +{ + u_char *sndbuf; + size_t sndlen; + struct snmp_pdu pdu; + enum snmpd_input_err ierr, ferr; + enum snmpd_proxy_err perr; + ssize_t ret, slen; + int32_t vi; +#ifdef USE_TCPWRAPPERS + char client[16]; +#endif + + ret = tport->transport->vtab->recv(tport, pi); + if (ret == -1) + return (-1); + +#ifdef USE_TCPWRAPPERS + /* + * In case of AF_INET{6} peer, do hosts_access(5) check. + */ + if (pi->peer->sa_family != AF_LOCAL && + inet_ntop(pi->peer->sa_family, + &((const struct sockaddr_in *)(const void *)pi->peer)->sin_addr, + client, sizeof(client)) != NULL) { + request_set(&req, RQ_CLIENT_ADDR, client, 0); + if (hosts_access(&req) == 0) { + syslog(LOG_ERR, "refused connection from %.500s", + eval_client(&req)); + return (-1); + } + } else if (pi->peer->sa_family != AF_LOCAL) + syslog(LOG_ERR, "inet_ntop(): %m"); +#endif + + /* + * Handle input + */ + ierr = snmp_input_start(pi->buf, pi->length, "SNMP", &pdu, &vi, + &pi->consumed); + if (ierr == SNMPD_INPUT_TRUNC) { + /* need more bytes. This is ok only for streaming transports. + * but only if we have not reached bufsiz yet. */ + if (pi->stream) { + if (pi->length == buf_size(0)) { + snmpd_stats.silentDrops++; + return (-1); + } + return (0); + } + snmpd_stats.silentDrops++; + return (-1); + } + + /* can't check for bad SET pdus here, because a proxy may have to + * check the access first. We don't want to return an error response + * to a proxy PDU with a wrong community */ + if (ierr == SNMPD_INPUT_FAILED) { + /* for streaming transports this is fatal */ + if (pi->stream) + return (-1); + snmp_input_consume(pi); + return (0); + } + if (ierr == SNMPD_INPUT_BAD_COMM) { + snmp_input_consume(pi); + return (0); + } + + /* + * If that is a module community and the module has a proxy function, + * the hand it over to the module. + */ + if (comm != NULL && comm->owner != NULL && + comm->owner->config->proxy != NULL) { + perr = (*comm->owner->config->proxy)(&pdu, tport->transport, + &tport->index, pi->peer, pi->peerlen, ierr, vi, + !pi->cred || pi->priv); + + switch (perr) { + + case SNMPD_PROXY_OK: + snmp_input_consume(pi); + return (0); + + case SNMPD_PROXY_REJ: + break; + + case SNMPD_PROXY_DROP: + snmp_input_consume(pi); + snmp_pdu_free(&pdu); + snmpd_stats.proxyDrops++; + return (0); + + case SNMPD_PROXY_BADCOMM: + snmp_input_consume(pi); + snmp_pdu_free(&pdu); + snmpd_stats.inBadCommunityNames++; + if (snmpd.auth_traps) + snmp_send_trap(&oid_authenticationFailure, + (struct snmp_value *)NULL); + return (0); + + case SNMPD_PROXY_BADCOMMUSE: + snmp_input_consume(pi); + snmp_pdu_free(&pdu); + snmpd_stats.inBadCommunityUses++; + if (snmpd.auth_traps) + snmp_send_trap(&oid_authenticationFailure, + (struct snmp_value *)NULL); + return (0); + } + } + + /* + * Check type + */ + if (pdu.type == SNMP_PDU_RESPONSE || + pdu.type == SNMP_PDU_TRAP || + pdu.type == SNMP_PDU_TRAP2) { + snmpd_stats.silentDrops++; + snmpd_stats.inBadPduTypes++; + snmp_pdu_free(&pdu); + snmp_input_consume(pi); + return (0); + } + + /* + * Check community + */ + if (pdu.version < SNMP_V3 && + ((pi->cred && !pi->priv && pdu.type == SNMP_PDU_SET) || + (comm != NULL && comm->private != COMM_WRITE && + (pdu.type == SNMP_PDU_SET || comm->private != COMM_READ)))) { + snmpd_stats.inBadCommunityUses++; + snmp_pdu_free(&pdu); + snmp_input_consume(pi); + if (snmpd.auth_traps) + snmp_send_trap(&oid_authenticationFailure, + (struct snmp_value *)NULL); + return (0); + } + + /* + * Execute it. + */ + if ((sndbuf = buf_alloc(1)) == NULL) { + snmpd_stats.silentDrops++; + snmp_pdu_free(&pdu); + snmp_input_consume(pi); + return (0); + } + ferr = snmp_input_finish(&pdu, pi->buf, pi->length, + sndbuf, &sndlen, "SNMP", ierr, vi, NULL); + + if (ferr == SNMPD_INPUT_OK) { + slen = tport->transport->vtab->send(tport, sndbuf, sndlen, + pi->peer, pi->peerlen); + if (slen == -1) + syslog(LOG_ERR, "send*: %m"); + else if ((size_t)slen != sndlen) + syslog(LOG_ERR, "send*: short write %zu/%zu", sndlen, + (size_t)slen); + } + + snmp_pdu_free(&pdu); + free(sndbuf); + snmp_input_consume(pi); + + return (0); +} + +/* + * Send a PDU to a given port + */ +void +snmp_send_port(void *targ, const struct asn_oid *port, struct snmp_pdu *pdu, + const struct sockaddr *addr, socklen_t addrlen) +{ + struct transport *trans = targ; + struct tport *tp; + u_char *sndbuf; + size_t sndlen; + ssize_t len; + + TAILQ_FOREACH(tp, &trans->table, link) + if (asn_compare_oid(port, &tp->index) == 0) + break; + if (tp == 0) + return; + + if ((sndbuf = buf_alloc(1)) == NULL) + return; + + snmp_output(pdu, sndbuf, &sndlen, "SNMP PROXY"); + + len = trans->vtab->send(tp, sndbuf, sndlen, addr, addrlen); + + if (len == -1) + syslog(LOG_ERR, "sendto: %m"); + else if ((size_t)len != sndlen) + syslog(LOG_ERR, "sendto: short write %zu/%zu", + sndlen, (size_t)len); + + free(sndbuf); +} + + +/* + * Close an input source + */ +void +snmpd_input_close(struct port_input *pi) +{ + if (pi->id != NULL) + fd_deselect(pi->id); + if (pi->fd >= 0) + (void)close(pi->fd); + if (pi->buf != NULL) + free(pi->buf); +} + +/* + * Dump internal state. + */ +#ifdef USE_LIBBEGEMOT +static void +info_func(void) +#else +static void +info_func(evContext ctx __unused, void *uap __unused, const void *tag __unused) +#endif +{ + struct lmodule *m; + u_int i; + char buf[10000]; + + syslog(LOG_DEBUG, "Dump of SNMPd %lu\n", (u_long)getpid()); + for (i = 0; i < tree_size; i++) { + switch (tree[i].type) { + + case SNMP_NODE_LEAF: + sprintf(buf, "LEAF: %s %s", tree[i].name, + asn_oid2str(&tree[i].oid)); + break; + + case SNMP_NODE_COLUMN: + sprintf(buf, "COL: %s %s", tree[i].name, + asn_oid2str(&tree[i].oid)); + break; + } + syslog(LOG_DEBUG, "%s", buf); + } + + TAILQ_FOREACH(m, &lmodules, link) + if (m->config->dump) + (*m->config->dump)(); +} + +/* + * Re-read configuration + */ +#ifdef USE_LIBBEGEMOT +static void +config_func(void) +#else +static void +config_func(evContext ctx __unused, void *uap __unused, + const void *tag __unused) +#endif +{ + struct lmodule *m; + + if (read_config(config_file, NULL)) { + syslog(LOG_ERR, "error reading config file '%s'", config_file); + return; + } + TAILQ_FOREACH(m, &lmodules, link) + if (m->config->config) + (*m->config->config)(); +} + +/* + * On USR1 dump actual configuration. + */ +static void +onusr1(int s __unused) +{ + + work |= WORK_DOINFO; +} +static void +onhup(int s __unused) +{ + + work |= WORK_RECONFIG; +} + +static void +onterm(int s __unused) +{ + + /* allow clean-up */ + exit(0); +} + +static void +init_sigs(void) +{ + struct sigaction sa; + + sa.sa_handler = onusr1; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGUSR1, &sa, NULL)) { + syslog(LOG_ERR, "sigaction: %m"); + exit(1); + } + + sa.sa_handler = onhup; + if (sigaction(SIGHUP, &sa, NULL)) { + syslog(LOG_ERR, "sigaction: %m"); + exit(1); + } + + sa.sa_handler = onterm; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGTERM, &sa, NULL)) { + syslog(LOG_ERR, "sigaction: %m"); + exit(1); + } + if (sigaction(SIGINT, &sa, NULL)) { + syslog(LOG_ERR, "sigaction: %m"); + exit(1); + } +} + +static void +block_sigs(void) +{ + sigset_t set; + + sigfillset(&set); + if (sigprocmask(SIG_BLOCK, &set, &blocked_sigs) == -1) { + syslog(LOG_ERR, "SIG_BLOCK: %m"); + exit(1); + } +} +static void +unblock_sigs(void) +{ + if (sigprocmask(SIG_SETMASK, &blocked_sigs, NULL) == -1) { + syslog(LOG_ERR, "SIG_SETMASK: %m"); + exit(1); + } +} + +/* + * Shut down + */ +static void +term(void) +{ + (void)unlink(pid_file); +} + +static void +trans_stop(void) +{ + struct transport *t; + + TAILQ_FOREACH(t, &transport_list, link) + (void)t->vtab->stop(1); +} + +/* + * Define a macro from the command line + */ +static void +do_macro(char *arg) +{ + char *eq; + int err; + + if ((eq = strchr(arg, '=')) == NULL) + err = define_macro(arg, ""); + else { + *eq++ = '\0'; + err = define_macro(arg, eq); + } + if (err == -1) { + syslog(LOG_ERR, "cannot save macro: %m"); + exit(1); + } +} + +/* + * Re-implement getsubopt from scratch, because the second argument is broken + * and will not compile with WARNS=5. + */ +static int +getsubopt1(char **arg, const char *const *options, char **valp, char **optp) +{ + static const char *const delim = ",\t "; + u_int i; + char *ptr; + + *optp = NULL; + + /* skip leading junk */ + for (ptr = *arg; *ptr != '\0'; ptr++) + if (strchr(delim, *ptr) == NULL) + break; + if (*ptr == '\0') { + *arg = ptr; + return (-1); + } + *optp = ptr; + + /* find the end of the option */ + while (*++ptr != '\0') + if (strchr(delim, *ptr) != NULL || *ptr == '=') + break; + + if (*ptr != '\0') { + if (*ptr == '=') { + *ptr++ = '\0'; + *valp = ptr; + while (*ptr != '\0' && strchr(delim, *ptr) == NULL) + ptr++; + if (*ptr != '\0') + *ptr++ = '\0'; + } else + *ptr++ = '\0'; + } + + *arg = ptr; + + for (i = 0; *options != NULL; options++, i++) + if (strcmp(*optp, *options) == 0) + return (i); + return (-1); +} + +int +main(int argc, char *argv[]) +{ + int opt; + FILE *fp; + int background = 1; + struct tport *p; + const char *prefix = "snmpd"; + struct lmodule *m; + char *value = NULL, *option; /* XXX */ + struct transport *t; + +#define DBG_DUMP 0 +#define DBG_EVENTS 1 +#define DBG_TRACE 2 + static const char *const debug_opts[] = { + "dump", + "events", + "trace", + NULL + }; + + snmp_printf = snmp_printf_func; + snmp_error = snmp_error_func; + snmp_debug = snmp_debug_func; + asn_error = asn_error_func; + + while ((opt = getopt(argc, argv, "c:dD:e:hI:l:m:p:")) != EOF) + switch (opt) { + + case 'c': + strlcpy(config_file, optarg, sizeof(config_file)); + break; + + case 'd': + background = 0; + break; + + case 'D': + while (*optarg) { + switch (getsubopt1(&optarg, debug_opts, + &value, &option)) { + + case DBG_DUMP: + debug.dump_pdus = 1; + break; + + case DBG_EVENTS: + debug.evdebug++; + break; + + case DBG_TRACE: + if (value == NULL) + syslog(LOG_ERR, + "no value for 'trace'"); + else + snmp_trace = strtoul(value, + NULL, 0); + break; + + case -1: + if (suboptarg) + syslog(LOG_ERR, + "unknown debug flag '%s'", + option); + else + syslog(LOG_ERR, + "missing debug flag"); + break; + } + } + break; + + case 'e': + strlcpy(engine_file, optarg, sizeof(engine_file)); + break; + case 'h': + fprintf(stderr, "%s", usgtxt); + exit(0); + + case 'I': + syspath = optarg; + break; + + case 'l': + prefix = optarg; + break; + + case 'm': + do_macro(optarg); + break; + + case 'p': + strlcpy(pid_file, optarg, sizeof(pid_file)); + break; + } + + openlog(prefix, LOG_PID | (background ? 0 : LOG_PERROR), LOG_USER); + setlogmask(LOG_UPTO(debug.logpri - 1)); + + if (background && daemon(0, 0) < 0) { + syslog(LOG_ERR, "daemon: %m"); + exit(1); + } + + argc -= optind; + argv += optind; + + progargs = argv; + nprogargs = argc; + + srandomdev(); + + snmp_serial_no = random(); + +#ifdef USE_TCPWRAPPERS + /* + * Initialize hosts_access(3) handler. + */ + request_init(&req, RQ_DAEMON, "snmpd", 0); + sock_methods(&req); +#endif + + /* + * Initialize the tree. + */ + if ((tree = malloc(sizeof(struct snmp_node) * CTREE_SIZE)) == NULL) { + syslog(LOG_ERR, "%m"); + exit(1); + } + memcpy(tree, ctree, sizeof(struct snmp_node) * CTREE_SIZE); + tree_size = CTREE_SIZE; + + /* + * Get standard communities + */ + comm_define(COMM_READ, "SNMP read", NULL, NULL); + comm_define(COMM_WRITE, "SNMP write", NULL, NULL); + community = COMM_INITIALIZE; + + trap_reqid = reqid_allocate(512, NULL); + + if (config_file[0] == '\0') + snprintf(config_file, sizeof(config_file), PATH_CONFIG, prefix); + + init_actvals(); + init_snmpd_engine(); + + this_tick = get_ticks(); + start_tick = this_tick; + + /* start transports */ + if (atexit(trans_stop) == -1) { + syslog(LOG_ERR, "atexit failed: %m"); + exit(1); + } + if (udp_trans.start() != SNMP_ERR_NOERROR) + syslog(LOG_WARNING, "cannot start UDP transport"); + if (lsock_trans.start() != SNMP_ERR_NOERROR) + syslog(LOG_WARNING, "cannot start LSOCK transport"); + +#ifdef USE_LIBBEGEMOT + if (debug.evdebug > 0) + rpoll_trace = 1; +#else + if (evCreate(&evctx)) { + syslog(LOG_ERR, "evCreate: %m"); + exit(1); + } + if (debug.evdebug > 0) + evSetDebug(evctx, 10, stderr); +#endif + + if (engine_file[0] == '\0') + snprintf(engine_file, sizeof(engine_file), PATH_ENGINE, prefix); + + if (read_config(config_file, NULL)) { + syslog(LOG_ERR, "error in config file"); + exit(1); + } + + TAILQ_FOREACH(t, &transport_list, link) + TAILQ_FOREACH(p, &t->table, link) + t->vtab->init_port(p); + + init_sigs(); + + if (pid_file[0] == '\0') + snprintf(pid_file, sizeof(pid_file), PATH_PID, prefix); + + if ((fp = fopen(pid_file, "w")) != NULL) { + fprintf(fp, "%u", getpid()); + fclose(fp); + if (atexit(term) == -1) { + syslog(LOG_ERR, "atexit failed: %m"); + (void)remove(pid_file); + exit(0); + } + } + + if (or_register(&oid_snmpMIB, "The MIB module for SNMPv2 entities.", + NULL) == 0) { + syslog(LOG_ERR, "cannot register SNMPv2 MIB"); + exit(1); + } + if (or_register(&oid_begemotSnmpd, "The MIB module for the Begemot SNMPd.", + NULL) == 0) { + syslog(LOG_ERR, "cannot register begemotSnmpd MIB"); + exit(1); + } + + while ((m = TAILQ_FIRST(&modules_start)) != NULL) { + m->flags &= ~LM_ONSTARTLIST; + TAILQ_REMOVE(&modules_start, m, start); + lm_start(m); + } + + snmp_send_trap(&oid_coldStart, (struct snmp_value *)NULL); + + for (;;) { +#ifndef USE_LIBBEGEMOT + evEvent event; +#endif + struct lmodule *mod; + + TAILQ_FOREACH(mod, &lmodules, link) + if (mod->config->idle != NULL) + (*mod->config->idle)(); + +#ifndef USE_LIBBEGEMOT + if (evGetNext(evctx, &event, EV_WAIT) == 0) { + if (evDispatch(evctx, event)) + syslog(LOG_ERR, "evDispatch: %m"); + } else if (errno != EINTR) { + syslog(LOG_ERR, "evGetNext: %m"); + exit(1); + } +#else + poll_dispatch(1); +#endif + + if (work != 0) { + block_sigs(); + if (work & WORK_DOINFO) { +#ifdef USE_LIBBEGEMOT + info_func(); +#else + if (evWaitFor(evctx, &work, info_func, + NULL, NULL) == -1) { + syslog(LOG_ERR, "evWaitFor: %m"); + exit(1); + } +#endif + } + if (work & WORK_RECONFIG) { +#ifdef USE_LIBBEGEMOT + config_func(); +#else + if (evWaitFor(evctx, &work, config_func, + NULL, NULL) == -1) { + syslog(LOG_ERR, "evWaitFor: %m"); + exit(1); + } +#endif + } + work = 0; + unblock_sigs(); +#ifndef USE_LIBBEGEMOT + if (evDo(evctx, &work) == -1) { + syslog(LOG_ERR, "evDo: %m"); + exit(1); + } +#endif + } + } + + return (0); +} + +uint64_t +get_ticks(void) +{ + struct timeval tv; + uint64_t ret; + + if (gettimeofday(&tv, NULL)) + abort(); + ret = tv.tv_sec * 100ULL + tv.tv_usec / 10000ULL; + return (ret); +} + +/* + * Timer support + */ + +/* + * Trampoline for the non-repeatable timers. + */ +#ifdef USE_LIBBEGEMOT +static void +tfunc(int tid __unused, void *uap) +#else +static void +tfunc(evContext ctx __unused, void *uap, struct timespec due __unused, + struct timespec inter __unused) +#endif +{ + struct timer *tp = uap; + + LIST_REMOVE(tp, link); + tp->func(tp->udata); + free(tp); +} + +/* + * Trampoline for the repeatable timers. + */ +#ifdef USE_LIBBEGEMOT +static void +trfunc(int tid __unused, void *uap) +#else +static void +trfunc(evContext ctx __unused, void *uap, struct timespec due __unused, + struct timespec inter __unused) +#endif +{ + struct timer *tp = uap; + + tp->func(tp->udata); +} + +/* + * Start a one-shot timer + */ +void * +timer_start(u_int ticks, void (*func)(void *), void *udata, struct lmodule *mod) +{ + struct timer *tp; +#ifndef USE_LIBBEGEMOT + struct timespec due; +#endif + + if ((tp = malloc(sizeof(struct timer))) == NULL) { + syslog(LOG_CRIT, "out of memory for timer"); + exit(1); + } + +#ifndef USE_LIBBEGEMOT + due = evAddTime(evNowTime(), + evConsTime(ticks / 100, (ticks % 100) * 10000)); +#endif + + tp->udata = udata; + tp->owner = mod; + tp->func = func; + + LIST_INSERT_HEAD(&timer_list, tp, link); + +#ifdef USE_LIBBEGEMOT + if ((tp->id = poll_start_timer(ticks * 10, 0, tfunc, tp)) < 0) { + syslog(LOG_ERR, "cannot set timer: %m"); + exit(1); + } +#else + if (evSetTimer(evctx, tfunc, tp, due, evConsTime(0, 0), &tp->id) + == -1) { + syslog(LOG_ERR, "cannot set timer: %m"); + exit(1); + } +#endif + return (tp); +} + +/* + * Start a repeatable timer. When used with USE_LIBBEGEMOT the first argument + * is currently ignored and the initial number of ticks is set to the + * repeat number of ticks. + */ +void * +timer_start_repeat(u_int ticks __unused, u_int repeat_ticks, + void (*func)(void *), void *udata, struct lmodule *mod) +{ + struct timer *tp; +#ifndef USE_LIBBEGEMOT + struct timespec due; + struct timespec inter; +#endif + + if ((tp = malloc(sizeof(struct timer))) == NULL) { + syslog(LOG_CRIT, "out of memory for timer"); + exit(1); + } + +#ifndef USE_LIBBEGEMOT + due = evAddTime(evNowTime(), + evConsTime(ticks / 100, (ticks % 100) * 10000)); + inter = evConsTime(repeat_ticks / 100, (repeat_ticks % 100) * 10000); +#endif + + tp->udata = udata; + tp->owner = mod; + tp->func = func; + + LIST_INSERT_HEAD(&timer_list, tp, link); + +#ifdef USE_LIBBEGEMOT + if ((tp->id = poll_start_timer(repeat_ticks * 10, 1, trfunc, tp)) < 0) { + syslog(LOG_ERR, "cannot set timer: %m"); + exit(1); + } +#else + if (evSetTimer(evctx, trfunc, tp, due, inter, &tp->id) == -1) { + syslog(LOG_ERR, "cannot set timer: %m"); + exit(1); + } +#endif + return (tp); +} + +/* + * Stop a timer. + */ +void +timer_stop(void *p) +{ + struct timer *tp = p; + + LIST_REMOVE(tp, link); +#ifdef USE_LIBBEGEMOT + poll_stop_timer(tp->id); +#else + if (evClearTimer(evctx, tp->id) == -1) { + syslog(LOG_ERR, "cannot stop timer: %m"); + exit(1); + } +#endif + free(p); +} + +static void +timer_flush(struct lmodule *mod) +{ + struct timer *t, *t1; + + t = LIST_FIRST(&timer_list); + while (t != NULL) { + t1 = LIST_NEXT(t, link); + if (t->owner == mod) + timer_stop(t); + t = t1; + } +} + +static void +snmp_printf_func(const char *fmt, ...) +{ + va_list ap; + static char *pend = NULL; + char *ret, *new; + + va_start(ap, fmt); + vasprintf(&ret, fmt, ap); + va_end(ap); + + if (ret == NULL) + return; + if (pend != NULL) { + if ((new = realloc(pend, strlen(pend) + strlen(ret) + 1)) + == NULL) { + free(ret); + return; + } + pend = new; + strcat(pend, ret); + free(ret); + } else + pend = ret; + + while ((ret = strchr(pend, '\n')) != NULL) { + *ret = '\0'; + syslog(LOG_DEBUG, "%s", pend); + if (strlen(ret + 1) == 0) { + free(pend); + pend = NULL; + break; + } + strcpy(pend, ret + 1); + } +} + +static void +snmp_error_func(const char *err, ...) +{ + char errbuf[1000]; + va_list ap; + + if (!(snmp_trace & LOG_SNMP_ERRORS)) + return; + + va_start(ap, err); + snprintf(errbuf, sizeof(errbuf), "SNMP: "); + vsnprintf(errbuf + strlen(errbuf), + sizeof(errbuf) - strlen(errbuf), err, ap); + va_end(ap); + + syslog(LOG_ERR, "%s", errbuf); +} + +static void +snmp_debug_func(const char *err, ...) +{ + char errbuf[1000]; + va_list ap; + + va_start(ap, err); + snprintf(errbuf, sizeof(errbuf), "SNMP: "); + vsnprintf(errbuf+strlen(errbuf), sizeof(errbuf)-strlen(errbuf), + err, ap); + va_end(ap); + + syslog(LOG_DEBUG, "%s", errbuf); +} + +static void +asn_error_func(const struct asn_buf *b, const char *err, ...) +{ + char errbuf[1000]; + va_list ap; + u_int i; + + if (!(snmp_trace & LOG_ASN1_ERRORS)) + return; + + va_start(ap, err); + snprintf(errbuf, sizeof(errbuf), "ASN.1: "); + vsnprintf(errbuf + strlen(errbuf), + sizeof(errbuf) - strlen(errbuf), err, ap); + va_end(ap); + + if (b != NULL) { + snprintf(errbuf + strlen(errbuf), + sizeof(errbuf) - strlen(errbuf), " at"); + for (i = 0; b->asn_len > i; i++) + snprintf(errbuf + strlen(errbuf), + sizeof(errbuf) - strlen(errbuf), + " %02x", b->asn_cptr[i]); + } + + syslog(LOG_ERR, "%s", errbuf); +} + +/* + * Create a new community + */ +struct community* +comm_define_ordered(u_int priv, const char *descr, struct asn_oid *idx, + struct lmodule *owner, const char *str) +{ + struct community *c, *p; + u_int ncomm; + + ncomm = idx->subs[idx->len - 1]; + + /* check that community doesn't already exist */ + TAILQ_FOREACH(c, &community_list, link) + if (c->value == ncomm) + return (c); + + if ((c = malloc(sizeof(struct community))) == NULL) { + syslog(LOG_ERR, "%s: %m", __func__); + return (NULL); + } + c->owner = owner; + c->value = ncomm; + c->descr = descr; + c->string = NULL; + c->private = priv; + + if (str != NULL) { + if((c->string = malloc(strlen(str)+1)) == NULL) { + free(c); + return (NULL); + } + strcpy(c->string, str); + } + /* + * Insert ordered + */ + c->index = *idx; + TAILQ_FOREACH(p, &community_list, link) { + if (asn_compare_oid(&p->index, &c->index) > 0) { + TAILQ_INSERT_BEFORE(p, c, link); + break; + } + } + if (p == NULL) + TAILQ_INSERT_TAIL(&community_list, c, link); + return (c); +} + +u_int +comm_define(u_int priv, const char *descr, struct lmodule *owner, + const char *str) +{ + struct asn_oid idx, *p; + struct community *c; + u_int ncomm; + + /* generate an identifier */ + do { + if ((ncomm = next_community_index++) == UINT_MAX) + next_community_index = 1; + TAILQ_FOREACH(c, &community_list, link) + if (c->value == ncomm) + break; + } while (c != NULL); + + /* make index */ + if (owner != NULL) + p = &owner->index; + else { + p = &idx; + p->len = 1; + p->subs[0] = 0; + } + p->subs[p->len++] = ncomm; + c = comm_define_ordered(priv, descr, p, owner, str); + if (c == NULL) + return (0); + return (c->value); +} + +const char * +comm_string(u_int ncomm) +{ + struct community *p; + + TAILQ_FOREACH(p, &community_list, link) + if (p->value == ncomm) + return (p->string); + return (NULL); +} + +/* + * Delete all communities allocated by a module + */ +static void +comm_flush(struct lmodule *mod) +{ + struct community *p, *p1; + + p = TAILQ_FIRST(&community_list); + while (p != NULL) { + p1 = TAILQ_NEXT(p, link); + if (p->owner == mod) { + free(p->string); + TAILQ_REMOVE(&community_list, p, link); + free(p); + } + p = p1; + } +} + +/* + * Request ID handling. + * + * Allocate a new range of request ids. Use a first fit algorithm. + */ +u_int +reqid_allocate(int size, struct lmodule *mod) +{ + u_int type; + struct idrange *r, *r1; + + if (size <= 0 || size > INT32_MAX) { + syslog(LOG_CRIT, "%s: size out of range: %d", __func__, size); + return (0); + } + /* allocate a type id */ + do { + if ((type = next_idrange++) == UINT_MAX) + next_idrange = 1; + TAILQ_FOREACH(r, &idrange_list, link) + if (r->type == type) + break; + } while(r != NULL); + + /* find a range */ + if (TAILQ_EMPTY(&idrange_list)) + r = NULL; + else { + r = TAILQ_FIRST(&idrange_list); + if (r->base < size) { + while((r1 = TAILQ_NEXT(r, link)) != NULL) { + if (r1->base - (r->base + r->size) >= size) + break; + r = r1; + } + r = r1; + } + if (r == NULL) { + r1 = TAILQ_LAST(&idrange_list, idrange_list); + if (INT32_MAX - size + 1 < r1->base + r1->size) { + syslog(LOG_ERR, "out of id ranges (%u)", size); + return (0); + } + } + } + + /* allocate structure */ + if ((r1 = malloc(sizeof(struct idrange))) == NULL) { + syslog(LOG_ERR, "%s: %m", __FUNCTION__); + return (0); + } + + r1->type = type; + r1->size = size; + r1->owner = mod; + if (TAILQ_EMPTY(&idrange_list) || r == TAILQ_FIRST(&idrange_list)) { + r1->base = 0; + TAILQ_INSERT_HEAD(&idrange_list, r1, link); + } else if (r == NULL) { + r = TAILQ_LAST(&idrange_list, idrange_list); + r1->base = r->base + r->size; + TAILQ_INSERT_TAIL(&idrange_list, r1, link); + } else { + r = TAILQ_PREV(r, idrange_list, link); + r1->base = r->base + r->size; + TAILQ_INSERT_AFTER(&idrange_list, r, r1, link); + } + r1->next = r1->base; + + return (type); +} + +int32_t +reqid_next(u_int type) +{ + struct idrange *r; + int32_t id; + + TAILQ_FOREACH(r, &idrange_list, link) + if (r->type == type) + break; + if (r == NULL) { + syslog(LOG_CRIT, "wrong idrange type"); + abort(); + } + if ((id = r->next++) == r->base + (r->size - 1)) + r->next = r->base; + return (id); +} + +int32_t +reqid_base(u_int type) +{ + struct idrange *r; + + TAILQ_FOREACH(r, &idrange_list, link) + if (r->type == type) + return (r->base); + syslog(LOG_CRIT, "wrong idrange type"); + abort(); +} + +u_int +reqid_type(int32_t reqid) +{ + struct idrange *r; + + TAILQ_FOREACH(r, &idrange_list, link) + if (reqid >= r->base && reqid <= r->base + (r->size - 1)) + return (r->type); + return (0); +} + +int +reqid_istype(int32_t reqid, u_int type) +{ + return (reqid_type(reqid) == type); +} + +/* + * Delete all communities allocated by a module + */ +static void +reqid_flush(struct lmodule *mod) +{ + struct idrange *p, *p1; + + p = TAILQ_FIRST(&idrange_list); + while (p != NULL) { + p1 = TAILQ_NEXT(p, link); + if (p->owner == mod) { + TAILQ_REMOVE(&idrange_list, p, link); + free(p); + } + p = p1; + } +} + +/* + * Merge the given tree for the given module into the main tree. + */ +static int +compare_node(const void *v1, const void *v2) +{ + const struct snmp_node *n1 = v1; + const struct snmp_node *n2 = v2; + + return (asn_compare_oid(&n1->oid, &n2->oid)); +} +static int +tree_merge(const struct snmp_node *ntree, u_int nsize, struct lmodule *mod) +{ + struct snmp_node *xtree; + u_int i; + + xtree = realloc(tree, sizeof(*tree) * (tree_size + nsize)); + if (xtree == NULL) { + syslog(LOG_ERR, "tree_merge: %m"); + return (-1); + } + tree = xtree; + memcpy(&tree[tree_size], ntree, sizeof(*tree) * nsize); + + for (i = 0; i < nsize; i++) + tree[tree_size + i].tree_data = mod; + + tree_size += nsize; + + qsort(tree, tree_size, sizeof(tree[0]), compare_node); + + return (0); +} + +/* + * Remove all nodes belonging to the loadable module + */ +static void +tree_unmerge(struct lmodule *mod) +{ + u_int s, d; + + for(s = d = 0; s < tree_size; s++) + if (tree[s].tree_data != mod) { + if (s != d) + tree[d] = tree[s]; + d++; + } + tree_size = d; +} + +/* + * Loadable modules + */ +struct lmodule * +lm_load(const char *path, const char *section) +{ + struct lmodule *m; + int err; + int i; + char *av[MAX_MOD_ARGS + 1]; + int ac; + u_int u; + + if ((m = malloc(sizeof(*m))) == NULL) { + syslog(LOG_ERR, "lm_load: %m"); + return (NULL); + } + m->handle = NULL; + m->flags = 0; + strlcpy(m->section, section, sizeof(m->section)); + + if ((m->path = strdup(path)) == NULL) { + syslog(LOG_ERR, "lm_load: %m"); + goto err; + } + + /* + * Make index + */ + m->index.subs[0] = strlen(section); + m->index.len = m->index.subs[0] + 1; + for (u = 0; u < m->index.subs[0]; u++) + m->index.subs[u + 1] = section[u]; + + /* + * Load the object file and locate the config structure + */ + if ((m->handle = dlopen(m->path, RTLD_NOW|RTLD_GLOBAL)) == NULL) { + syslog(LOG_ERR, "lm_load: open %s", dlerror()); + goto err; + } + + if ((m->config = dlsym(m->handle, "config")) == NULL) { + syslog(LOG_ERR, "lm_load: no 'config' symbol %s", dlerror()); + goto err; + } + + /* + * Insert it into the right place + */ + INSERT_OBJECT_OID(m, &lmodules); + + /* preserve order */ + if (community == COMM_INITIALIZE) { + m->flags |= LM_ONSTARTLIST; + TAILQ_INSERT_TAIL(&modules_start, m, start); + } + + /* + * make the argument vector. + */ + ac = 0; + for (i = 0; i < nprogargs; i++) { + if (strlen(progargs[i]) >= strlen(section) + 1 && + strncmp(progargs[i], section, strlen(section)) == 0 && + progargs[i][strlen(section)] == ':') { + if (ac == MAX_MOD_ARGS) { + syslog(LOG_WARNING, "too many arguments for " + "module '%s", section); + break; + } + av[ac++] = &progargs[i][strlen(section)+1]; + } + } + av[ac] = NULL; + + /* + * Run the initialization function + */ + if ((err = (*m->config->init)(m, ac, av)) != 0) { + syslog(LOG_ERR, "lm_load: init failed: %d", err); + TAILQ_REMOVE(&lmodules, m, link); + goto err; + } + + return (m); + + err: + if ((m->flags & LM_ONSTARTLIST) != 0) + TAILQ_REMOVE(&modules_start, m, start); + if (m->handle) + dlclose(m->handle); + free(m->path); + free(m); + return (NULL); +} + +/* + * Start a module + */ +void +lm_start(struct lmodule *mod) +{ + const struct lmodule *m; + + /* + * Merge tree. If this fails, unload the module. + */ + if (tree_merge(mod->config->tree, mod->config->tree_size, mod)) { + lm_unload(mod); + return; + } + + /* + * Read configuration + */ + if (read_config(config_file, mod)) { + syslog(LOG_ERR, "error in config file"); + lm_unload(mod); + return; + } + if (mod->config->start) + (*mod->config->start)(); + + mod->flags |= LM_STARTED; + + /* + * Inform other modules + */ + TAILQ_FOREACH(m, &lmodules, link) + if (m->config->loading) + (*m->config->loading)(mod, 1); +} + + +/* + * Unload a module. + */ +void +lm_unload(struct lmodule *m) +{ + int err; + const struct lmodule *mod; + + TAILQ_REMOVE(&lmodules, m, link); + if (m->flags & LM_ONSTARTLIST) + TAILQ_REMOVE(&modules_start, m, start); + tree_unmerge(m); + + if ((m->flags & LM_STARTED) && m->config->fini && + (err = (*m->config->fini)()) != 0) + syslog(LOG_WARNING, "lm_unload(%s): fini %d", m->section, err); + + comm_flush(m); + reqid_flush(m); + timer_flush(m); + fd_flush(m); + + dlclose(m->handle); + free(m->path); + + /* + * Inform other modules + */ + TAILQ_FOREACH(mod, &lmodules, link) + if (mod->config->loading) + (*mod->config->loading)(m, 0); + + free(m); +} + +/* + * Register an object resource and return the index (or 0 on failures) + */ +u_int +or_register(const struct asn_oid *or, const char *descr, struct lmodule *mod) +{ + struct objres *objres, *or1; + u_int idx; + + /* find a free index */ + idx = 1; + for (objres = TAILQ_FIRST(&objres_list); + objres != NULL; + objres = TAILQ_NEXT(objres, link)) { + if ((or1 = TAILQ_NEXT(objres, link)) == NULL || + or1->index > objres->index + 1) { + idx = objres->index + 1; + break; + } + } + + if ((objres = malloc(sizeof(*objres))) == NULL) + return (0); + + objres->index = idx; + objres->oid = *or; + strlcpy(objres->descr, descr, sizeof(objres->descr)); + objres->uptime = (uint32_t)(get_ticks() - start_tick); + objres->module = mod; + + INSERT_OBJECT_INT(objres, &objres_list); + + systemg.or_last_change = objres->uptime; + + return (idx); +} + +void +or_unregister(u_int idx) +{ + struct objres *objres; + + TAILQ_FOREACH(objres, &objres_list, link) + if (objres->index == idx) { + TAILQ_REMOVE(&objres_list, objres, link); + free(objres); + return; + } +} + +/* + * RFC 3414 User-based Security Model support + */ + +struct snmpd_usmstat * +bsnmpd_get_usm_stats(void) +{ + return (&snmpd_usmstats); +} + +void +bsnmpd_reset_usm_stats(void) +{ + memset(&snmpd_usmstats, 0, sizeof(snmpd_usmstats)); +} + +struct usm_user * +usm_first_user(void) +{ + return (SLIST_FIRST(&usm_userlist)); +} + +struct usm_user * +usm_next_user(struct usm_user *uuser) +{ + if (uuser == NULL) + return (NULL); + + return (SLIST_NEXT(uuser, up)); +} + +struct usm_user * +usm_find_user(uint8_t *engine, uint32_t elen, char *uname) +{ + struct usm_user *uuser; + + SLIST_FOREACH(uuser, &usm_userlist, up) + if (uuser->user_engine_len == elen && + memcmp(uuser->user_engine_id, engine, elen) == 0 && + strlen(uuser->suser.sec_name) == strlen(uname) && + strcmp(uuser->suser.sec_name, uname) == 0) + break; + + return (uuser); +} + +static int +usm_compare_user(struct usm_user *u1, struct usm_user *u2) +{ + uint32_t i; + + if (u1->user_engine_len < u2->user_engine_len) + return (-1); + if (u1->user_engine_len > u2->user_engine_len) + return (1); + + for (i = 0; i < u1->user_engine_len; i++) { + if (u1->user_engine_id[i] < u2->user_engine_id[i]) + return (-1); + if (u1->user_engine_id[i] > u2->user_engine_id[i]) + return (1); + } + + if (strlen(u1->suser.sec_name) < strlen(u2->suser.sec_name)) + return (-1); + if (strlen(u1->suser.sec_name) > strlen(u2->suser.sec_name)) + return (1); + + for (i = 0; i < strlen(u1->suser.sec_name); i++) { + if (u1->suser.sec_name[i] < u2->suser.sec_name[i]) + return (-1); + if (u1->suser.sec_name[i] > u2->suser.sec_name[i]) + return (1); + } + + return (0); +} + +struct usm_user * +usm_new_user(uint8_t *eid, uint32_t elen, char *uname) +{ + int cmp; + struct usm_user *uuser, *temp, *prev; + + for (uuser = usm_first_user(); uuser != NULL; + (uuser = usm_next_user(uuser))) { + if (uuser->user_engine_len == elen && + strlen(uname) == strlen(uuser->suser.sec_name) && + strcmp(uname, uuser->suser.sec_name) == 0 && + memcmp(eid, uuser->user_engine_id, elen) == 0) + return (NULL); + } + + if ((uuser = (struct usm_user *)malloc(sizeof(*uuser))) == NULL) + return (NULL); + + memset(uuser, 0, sizeof(*uuser)); + strlcpy(uuser->suser.sec_name, uname, SNMP_ADM_STR32_SIZ); + memcpy(uuser->user_engine_id, eid, elen); + uuser->user_engine_len = elen; + + if ((prev = SLIST_FIRST(&usm_userlist)) == NULL || + usm_compare_user(uuser, prev) < 0) { + SLIST_INSERT_HEAD(&usm_userlist, uuser, up); + return (uuser); + } + + SLIST_FOREACH(temp, &usm_userlist, up) { + if ((cmp = usm_compare_user(uuser, temp)) <= 0) + break; + prev = temp; + } + + if (temp == NULL || cmp < 0) + SLIST_INSERT_AFTER(prev, uuser, up); + else if (cmp > 0) + SLIST_INSERT_AFTER(temp, uuser, up); + else { + syslog(LOG_ERR, "User %s exists", uuser->suser.sec_name); + free(uuser); + return (NULL); + } + + return (uuser); +} + +void +usm_delete_user(struct usm_user *uuser) +{ + SLIST_REMOVE(&usm_userlist, uuser, usm_user, up); + free(uuser); +} + +void +usm_flush_users(void) +{ + struct usm_user *uuser; + + while ((uuser = SLIST_FIRST(&usm_userlist)) != NULL) { + SLIST_REMOVE_HEAD(&usm_userlist, up); + free(uuser); + } + + SLIST_INIT(&usm_userlist); +} + +/* + * RFC 3415 View-based Access Control Model support + */ +struct vacm_user * +vacm_first_user(void) +{ + return (SLIST_FIRST(&vacm_userlist)); +} + +struct vacm_user * +vacm_next_user(struct vacm_user *vuser) +{ + if (vuser == NULL) + return (NULL); + + return (SLIST_NEXT(vuser, vvu)); +} + +static int +vacm_compare_user(struct vacm_user *v1, struct vacm_user *v2) +{ + uint32_t i; + + if (v1->sec_model < v2->sec_model) + return (-1); + if (v1->sec_model > v2->sec_model) + return (1); + + if (strlen(v1->secname) < strlen(v2->secname)) + return (-1); + if (strlen(v1->secname) > strlen(v2->secname)) + return (1); + + for (i = 0; i < strlen(v1->secname); i++) { + if (v1->secname[i] < v2->secname[i]) + return (-1); + if (v1->secname[i] > v2->secname[i]) + return (1); + } + + return (0); +} + +struct vacm_user * +vacm_new_user(int32_t smodel, char *uname) +{ + int cmp; + struct vacm_user *user, *temp, *prev; + + SLIST_FOREACH(user, &vacm_userlist, vvu) + if (strcmp(uname, user->secname) == 0 && + smodel == user->sec_model) + return (NULL); + + if ((user = (struct vacm_user *)malloc(sizeof(*user))) == NULL) + return (NULL); + + memset(user, 0, sizeof(*user)); + user->group = &vacm_default_group; + SLIST_INSERT_HEAD(&vacm_default_group.group_users, user, vvg); + user->sec_model = smodel; + strlcpy(user->secname, uname, sizeof(user->secname)); + + if ((prev = SLIST_FIRST(&vacm_userlist)) == NULL || + vacm_compare_user(user, prev) < 0) { + SLIST_INSERT_HEAD(&vacm_userlist, user, vvu); + return (user); + } + + SLIST_FOREACH(temp, &vacm_userlist, vvu) { + if ((cmp = vacm_compare_user(user, temp)) <= 0) + break; + prev = temp; + } + + if (temp == NULL || cmp < 0) + SLIST_INSERT_AFTER(prev, user, vvu); + else if (cmp > 0) + SLIST_INSERT_AFTER(temp, user, vvu); + else { + syslog(LOG_ERR, "User %s exists", user->secname); + free(user); + return (NULL); + } + + return (user); +} + +int +vacm_delete_user(struct vacm_user *user) +{ + if (user->group != NULL && user->group != &vacm_default_group) { + SLIST_REMOVE(&user->group->group_users, user, vacm_user, vvg); + if (SLIST_EMPTY(&user->group->group_users)) { + SLIST_REMOVE(&vacm_grouplist, user->group, + vacm_group, vge); + free(user->group); + } + } + + SLIST_REMOVE(&vacm_userlist, user, vacm_user, vvu); + free(user); + + return (0); +} + +int +vacm_user_set_group(struct vacm_user *user, u_char *octets, u_int len) +{ + struct vacm_group *group; + + if (len >= SNMP_ADM_STR32_SIZ) + return (-1); + + SLIST_FOREACH(group, &vacm_grouplist, vge) + if (strlen(group->groupname) == len && + memcmp(octets, group->groupname, len) == 0) + break; + + if (group == NULL) { + if ((group = (struct vacm_group *)malloc(sizeof(*group))) == NULL) + return (-1); + memset(group, 0, sizeof(*group)); + memcpy(group->groupname, octets, len); + group->groupname[len] = '\0'; + SLIST_INSERT_HEAD(&vacm_grouplist, group, vge); + } + + SLIST_REMOVE(&user->group->group_users, user, vacm_user, vvg); + SLIST_INSERT_HEAD(&group->group_users, user, vvg); + user->group = group; + + return (0); +} + +void +vacm_groups_init(void) +{ + SLIST_INSERT_HEAD(&vacm_grouplist, &vacm_default_group, vge); +} + +struct vacm_access * +vacm_first_access_rule(void) +{ + return (TAILQ_FIRST(&vacm_accesslist)); +} + +struct vacm_access * +vacm_next_access_rule(struct vacm_access *acl) +{ + if (acl == NULL) + return (NULL); + + return (TAILQ_NEXT(acl, vva)); +} + +static int +vacm_compare_access_rule(struct vacm_access *v1, struct vacm_access *v2) +{ + uint32_t i; + + if (strlen(v1->group->groupname) < strlen(v2->group->groupname)) + return (-1); + if (strlen(v1->group->groupname) > strlen(v2->group->groupname)) + return (1); + + for (i = 0; i < strlen(v1->group->groupname); i++) { + if (v1->group->groupname[i] < v2->group->groupname[i]) + return (-1); + if (v1->group->groupname[i] > v2->group->groupname[i]) + return (1); + } + + if (strlen(v1->ctx_prefix) < strlen(v2->ctx_prefix)) + return (-1); + if (strlen(v1->ctx_prefix) > strlen(v2->ctx_prefix)) + return (1); + + for (i = 0; i < strlen(v1->ctx_prefix); i++) { + if (v1->ctx_prefix[i] < v2->ctx_prefix[i]) + return (-1); + if (v1->ctx_prefix[i] > v2->ctx_prefix[i]) + return (1); + } + + if (v1->sec_model < v2->sec_model) + return (-1); + if (v1->sec_model > v2->sec_model) + return (1); + + if (v1->sec_level < v2->sec_level) + return (-1); + if (v1->sec_level > v2->sec_level) + return (1); + + return (0); +} + +struct vacm_access * +vacm_new_access_rule(char *gname, char *cprefix, int32_t smodel, int32_t slevel) +{ + struct vacm_group *group; + struct vacm_access *acl, *temp; + + TAILQ_FOREACH(acl, &vacm_accesslist, vva) { + if (acl->group == NULL) + continue; + if (strcmp(gname, acl->group->groupname) == 0 && + strcmp(cprefix, acl->ctx_prefix) == 0 && + acl->sec_model == smodel && acl->sec_level == slevel) + return (NULL); + } + + /* Make sure the group exists */ + SLIST_FOREACH(group, &vacm_grouplist, vge) + if (strcmp(gname, group->groupname) == 0) + break; + + if (group == NULL) + return (NULL); + + if ((acl = (struct vacm_access *)malloc(sizeof(*acl))) == NULL) + return (NULL); + + memset(acl, 0, sizeof(*acl)); + acl->group = group; + strlcpy(acl->ctx_prefix, cprefix, sizeof(acl->ctx_prefix)); + acl->sec_model = smodel; + acl->sec_level = slevel; + + if ((temp = TAILQ_FIRST(&vacm_accesslist)) == NULL || + vacm_compare_access_rule(acl, temp) < 0) { + TAILQ_INSERT_HEAD(&vacm_accesslist, acl, vva); + return (acl); + } + + TAILQ_FOREACH(temp, &vacm_accesslist, vva) + if (vacm_compare_access_rule(acl, temp) < 0) { + TAILQ_INSERT_BEFORE(temp, acl, vva); + return (acl); + } + + TAILQ_INSERT_TAIL(&vacm_accesslist, acl, vva); + + return (acl); +} + +int +vacm_delete_access_rule(struct vacm_access *acl) +{ + TAILQ_REMOVE(&vacm_accesslist, acl, vva); + free(acl); + + return (0); +} + +struct vacm_view * +vacm_first_view(void) +{ + return (SLIST_FIRST(&vacm_viewlist)); +} + +struct vacm_view * +vacm_next_view(struct vacm_view *view) +{ + if (view == NULL) + return (NULL); + + return (SLIST_NEXT(view, vvl)); +} + +static int +vacm_compare_view(struct vacm_view *v1, struct vacm_view *v2) +{ + uint32_t i; + + if (strlen(v1->viewname) < strlen(v2->viewname)) + return (-1); + if (strlen(v1->viewname) > strlen(v2->viewname)) + return (1); + + for (i = 0; i < strlen(v1->viewname); i++) { + if (v1->viewname[i] < v2->viewname[i]) + return (-1); + if (v1->viewname[i] > v2->viewname[i]) + return (1); + } + + return (asn_compare_oid(&v1->subtree, &v2->subtree)); +} + +struct vacm_view * +vacm_new_view(char *vname, struct asn_oid *oid) +{ + int cmp; + struct vacm_view *view, *temp, *prev; + + SLIST_FOREACH(view, &vacm_viewlist, vvl) + if (strcmp(vname, view->viewname) == 0) + return (NULL); + + if ((view = (struct vacm_view *)malloc(sizeof(*view))) == NULL) + return (NULL); + + memset(view, 0, sizeof(*view)); + strlcpy(view->viewname, vname, sizeof(view->viewname)); + asn_append_oid(&view->subtree, oid); + + if ((prev = SLIST_FIRST(&vacm_viewlist)) == NULL || + vacm_compare_view(view, prev) < 0) { + SLIST_INSERT_HEAD(&vacm_viewlist, view, vvl); + return (view); + } + + SLIST_FOREACH(temp, &vacm_viewlist, vvl) { + if ((cmp = vacm_compare_view(view, temp)) <= 0) + break; + prev = temp; + } + + if (temp == NULL || cmp < 0) + SLIST_INSERT_AFTER(prev, view, vvl); + else if (cmp > 0) + SLIST_INSERT_AFTER(temp, view, vvl); + else { + syslog(LOG_ERR, "View %s exists", view->viewname); + free(view); + return (NULL); + } + + return (view); +} + +int +vacm_delete_view(struct vacm_view *view) +{ + SLIST_REMOVE(&vacm_viewlist, view, vacm_view, vvl); + free(view); + + return (0); +} + +struct vacm_context * +vacm_first_context(void) +{ + return (SLIST_FIRST(&vacm_contextlist)); +} + +struct vacm_context * +vacm_next_context(struct vacm_context *vacmctx) +{ + if (vacmctx == NULL) + return (NULL); + + return (SLIST_NEXT(vacmctx, vcl)); +} + +struct vacm_context * +vacm_add_context(char *ctxname, int regid) +{ + int cmp; + struct vacm_context *ctx, *temp, *prev; + + SLIST_FOREACH(ctx, &vacm_contextlist, vcl) + if (strcmp(ctxname, ctx->ctxname) == 0) { + syslog(LOG_ERR, "Context %s exists", ctx->ctxname); + return (NULL); + } + + if ((ctx = (struct vacm_context *)malloc(sizeof(*ctx))) == NULL) + return (NULL); + + memset(ctx, 0, sizeof(*ctx)); + strlcpy(ctx->ctxname, ctxname, sizeof(ctx->ctxname)); + ctx->regid = regid; + + if ((prev = SLIST_FIRST(&vacm_contextlist)) == NULL || + strlen(ctx->ctxname) < strlen(prev->ctxname) || + strcmp(ctx->ctxname, prev->ctxname) < 0) { + SLIST_INSERT_HEAD(&vacm_contextlist, ctx, vcl); + return (ctx); + } + + SLIST_FOREACH(temp, &vacm_contextlist, vcl) { + if (strlen(ctx->ctxname) < strlen(temp->ctxname) || + strcmp(ctx->ctxname, temp->ctxname) < 0) { + cmp = -1; + break; + } + prev = temp; + } + + if (temp == NULL || cmp < 0) + SLIST_INSERT_AFTER(prev, ctx, vcl); + else if (cmp > 0) + SLIST_INSERT_AFTER(temp, ctx, vcl); + else { + syslog(LOG_ERR, "Context %s exists", ctx->ctxname); + free(ctx); + return (NULL); + } + + return (ctx); +} + +void +vacm_flush_contexts(int regid) +{ + struct vacm_context *ctx, *temp; + + SLIST_FOREACH_SAFE(ctx, &vacm_contextlist, vcl, temp) + if (ctx->regid == regid) { + SLIST_REMOVE(&vacm_contextlist, ctx, vacm_context, vcl); + free(ctx); + } +} Property changes on: vendor/bsnmp/1.13/snmpd/main.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/snmpd.config =================================================================== --- vendor/bsnmp/1.13/snmpd/snmpd.config (nonexistent) +++ vendor/bsnmp/1.13/snmpd/snmpd.config (revision 336778) @@ -0,0 +1,104 @@ +# +# Copyright (c) 2001-2003 +# Fraunhofer Institute for Open Communication Systems (FhG Fokus). +# All rights reserved. +# +# Author: Harti Brandt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Begemot: bsnmp/snmpd/snmpd.config,v 1.16 2006/02/14 09:04:20 brandt_h Exp $ +# +# Example configuration file. +# + +# +# Set some common variables +# +host := foo.bar.com +location := "Room 200" +contact := "sysmeister@bar.com" +system := 1 # FreeBSD +traphost := noc.bar.com +trapport := 162 + +read := "public" +# Uncomment the line below that sets the community string +# to enable write access. +write := "geheim" +trap := "mytrap" + +# +# Configuration +# +%snmpd +begemotSnmpdDebugDumpPdus = 2 +begemotSnmpdDebugSyslogPri = 7 + +# +# Set the read and write communities. +# +# The default value of the community strings is NULL (note, that this is +# different from the empty string). This disables both read and write access. +# To enable read access only the read community string must be set. Setting +# the write community string enables both read and write access with that +# string. +# +# Be sure to understand the security implications of SNMPv2 - the community +# strings are readable on the wire! +# +begemotSnmpdCommunityString.0.1 = $(read) +# begemotSnmpdCommunityString.0.2 = $(write) +# begemotSnmpdCommunityString.0.3 = "otherPublic" +begemotSnmpdCommunityDisable = 1 + +# open standard SNMP ports +begemotSnmpdPortStatus.[$(host)].161 = 1 +begemotSnmpdPortStatus.127.0.0.1.161 = 1 + +# open a unix domain socket +begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1 +begemotSnmpdLocalPortType."/var/run/snmpd.sock" = 4 + +# send traps to the traphost +begemotTrapSinkStatus.[$(traphost)].$(trapport) = 4 +begemotTrapSinkVersion.[$(traphost)].$(trapport) = 2 +begemotTrapSinkComm.[$(traphost)].$(trapport) = $(trap) + +sysContact = $(contact) +sysLocation = $(location) +sysObjectId = 1.3.6.1.4.1.12325.1.1.2.1.$(system) + +snmpEnableAuthenTraps = 2 + +# +# Load MIB-2 module +# +begemotSnmpdModulePath."mibII" = "/usr/local/lib/snmp_mibII.so" + +# +# Netgraph module +# +begemotSnmpdModulePath."netgraph" = "/usr/local/lib/snmp_netgraph.so" + +%netgraph +begemotNgControlNodeName = "snmpd" Property changes on: vendor/bsnmp/1.13/snmpd/snmpd.config ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/snmpd.h =================================================================== --- vendor/bsnmp/1.13/snmpd/snmpd.h (nonexistent) +++ vendor/bsnmp/1.13/snmpd/snmpd.h (revision 336778) @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmpd/snmpd.h,v 1.24 2004/08/06 08:47:13 brandt Exp $ + * + * Private SNMPd data and functions. + */ + +#ifdef USE_LIBBEGEMOT +#include +#else +#include +#endif + +#define PATH_SYSCONFIG "/etc:/usr/etc:/usr/local/etc" + +#ifdef USE_LIBBEGEMOT +#define evTimerID int +#define evFileID int +#endif + +/************************************************************* + * + * Communities + */ +struct community { + struct lmodule *owner; /* who created the community */ + u_int private;/* private name for the module */ + u_int value; /* value of this community */ + u_char * string; /* the community string */ + const u_char * descr; /* description */ + TAILQ_ENTRY(community) link; + + struct asn_oid index; +}; +/* list of all known communities */ +extern TAILQ_HEAD(community_list, community) community_list; + +/************************************************************* + * + * Request IDs. + */ +struct idrange { + u_int type; /* type id */ + int32_t base; /* base of this range */ + int32_t size; /* size of this range */ + int32_t next; /* generator */ + struct lmodule *owner; /* owner module */ + TAILQ_ENTRY(idrange) link; +}; + +/* list of all known ranges */ +extern TAILQ_HEAD(idrange_list, idrange) idrange_list; + +/* identifier generator */ +extern u_int next_idrange; + +/* request id generator for traps */ +extern u_int trap_reqid; + +/************************************************************* + * + * Timers + */ +struct timer { + void (*func)(void *);/* user function */ + void *udata; /* user data */ + evTimerID id; /* timer id */ + struct lmodule *owner; /* owner of the timer */ + LIST_ENTRY(timer) link; +}; + +/* list of all current timers */ +extern LIST_HEAD(timer_list, timer) timer_list; + + +/************************************************************* + * + * File descriptors + */ +struct fdesc { + int fd; /* the file descriptor */ + void (*func)(int, void *);/* user function */ + void *udata; /* user data */ + evFileID id; /* file id */ + struct lmodule *owner; /* owner module of the file */ + LIST_ENTRY(fdesc) link; +}; + +/* list of all current selected files */ +extern LIST_HEAD(fdesc_list, fdesc) fdesc_list; + +/************************************************************* + * + * Loadable modules + */ +# define LM_SECTION_MAX 14 +struct lmodule { + char section[LM_SECTION_MAX + 1]; /* and index */ + char *path; + u_int flags; + void *handle; + const struct snmp_module *config; + + TAILQ_ENTRY(lmodule) link; + TAILQ_ENTRY(lmodule) start; + + struct asn_oid index; +}; +#define LM_STARTED 0x0001 +#define LM_ONSTARTLIST 0x0002 + +extern TAILQ_HEAD(lmodules, lmodule) lmodules; + +struct lmodule *lm_load(const char *, const char *); +void lm_unload(struct lmodule *); +void lm_start(struct lmodule *); + +/************************************************************* + * + * SNMP ports + */ +/* + * Common input stuff + */ +struct port_input { + int fd; /* socket */ + void *id; /* evSelect handle */ + + int stream : 1; /* stream socket */ + int cred : 1; /* want credentials */ + + struct sockaddr *peer; /* last received packet */ + socklen_t peerlen; + int priv : 1; /* peer is privileged */ + + u_char *buf; /* receive buffer */ + size_t buflen; /* buffer length */ + size_t length; /* received length */ + size_t consumed; /* how many bytes used */ +}; + +struct tport { + struct asn_oid index; /* table index of this tp point */ + TAILQ_ENTRY(tport) link; /* table link */ + struct transport *transport; /* who handles this */ +}; +TAILQ_HEAD(tport_list, tport); + +int snmpd_input(struct port_input *, struct tport *); +void snmpd_input_close(struct port_input *); + + +/* + * Transport domain + */ +#define TRANS_NAMELEN 64 + +struct transport_def { + const char *name; /* name of this transport */ + struct asn_oid id; /* OBJID of this transport */ + + int (*start)(void); + int (*stop)(int); + + void (*close_port)(struct tport *); + int (*init_port)(struct tport *); + + ssize_t (*send)(struct tport *, const u_char *, size_t, + const struct sockaddr *, size_t); + ssize_t (*recv)(struct tport *, struct port_input *); +}; +struct transport { + struct asn_oid index; /* transport table index */ + TAILQ_ENTRY(transport) link; /* ... and link */ + u_int or_index; /* registration index */ + + struct tport_list table; /* list of open ports */ + + const struct transport_def *vtab; +}; + +TAILQ_HEAD(transport_list, transport); +extern struct transport_list transport_list; + +void trans_insert_port(struct transport *, struct tport *); +void trans_remove_port(struct tport *); +struct tport *trans_find_port(struct transport *, + const struct asn_oid *, u_int); +struct tport *trans_next_port(struct transport *, + const struct asn_oid *, u_int); +struct tport *trans_first_port(struct transport *); +struct tport *trans_iter_port(struct transport *, + int (*)(struct tport *, intptr_t), intptr_t); + +int trans_register(const struct transport_def *, struct transport **); +int trans_unregister(struct transport *); + +/************************************************************* + * + * SNMPd scalar configuration. + */ +struct snmpd { + /* transmit buffer size */ + u_int32_t txbuf; + + /* receive buffer size */ + u_int32_t rxbuf; + + /* disable community table */ + int comm_dis; + + /* authentication traps */ + int auth_traps; + + /* source address for V1 traps */ + u_char trap1addr[4]; + + /* version enable flags */ + uint32_t version_enable; +}; +extern struct snmpd snmpd; + +#define VERS_ENABLE_V1 0x00000001 +#define VERS_ENABLE_V2C 0x00000002 +#define VERS_ENABLE_V3 0x00000004 +#define VERS_ENABLE_ALL (VERS_ENABLE_V1 | VERS_ENABLE_V2C | VERS_ENABLE_V3) + +/* + * The debug group + */ +struct debug { + u_int dump_pdus; + u_int logpri; + u_int evdebug; +}; +extern struct debug debug; + + +/* + * SNMPd statistics table + */ +struct snmpd_stats { + u_int32_t inPkts; /* total packets received */ + u_int32_t inBadVersions; /* unknown version number */ + u_int32_t inASNParseErrs; /* fatal parse errors */ + u_int32_t inBadCommunityNames; + u_int32_t inBadCommunityUses; + u_int32_t proxyDrops; /* dropped by proxy function */ + u_int32_t silentDrops; + + u_int32_t inBadPduTypes; + u_int32_t inTooLong; + u_int32_t noTxbuf; + u_int32_t noRxbuf; +}; +extern struct snmpd_stats snmpd_stats; + +/* + * SNMPd Engine + */ +extern struct snmp_engine snmpd_engine; + +/* + * OR Table + */ +struct objres { + TAILQ_ENTRY(objres) link; + u_int index; + struct asn_oid oid; /* the resource OID */ + char descr[256]; + u_int32_t uptime; + struct lmodule *module; +}; +TAILQ_HEAD(objres_list, objres); +extern struct objres_list objres_list; + +/* + * Trap Sink Table + */ +struct trapsink { + TAILQ_ENTRY(trapsink) link; + struct asn_oid index; + u_int status; + int socket; + u_char comm[SNMP_COMMUNITY_MAXLEN + 1]; + int version; +}; +enum { + TRAPSINK_ACTIVE = 1, + TRAPSINK_NOT_IN_SERVICE = 2, + TRAPSINK_NOT_READY = 3, + TRAPSINK_DESTROY = 6, + + TRAPSINK_V1 = 1, + TRAPSINK_V2 = 2, +}; +TAILQ_HEAD(trapsink_list, trapsink); +extern struct trapsink_list trapsink_list; + +extern const char *syspath; + +/* snmpSerialNo */ +extern int32_t snmp_serial_no; + +int init_actvals(void); + +extern char engine_file[]; +int init_snmpd_engine(void); +int set_snmpd_engine(void); +void update_snmpd_engine_time(void); + +int read_config(const char *, struct lmodule *); +int define_macro(const char *name, const char *value); + +#define LOG_ASN1_ERRORS 0x10000000 +#define LOG_SNMP_ERRORS 0x20000000 Property changes on: vendor/bsnmp/1.13/snmpd/snmpd.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/snmpd.sh =================================================================== --- vendor/bsnmp/1.13/snmpd/snmpd.sh (nonexistent) +++ vendor/bsnmp/1.13/snmpd/snmpd.sh (revision 336778) @@ -0,0 +1,85 @@ +#!/bin/sh +# +# Copyright (c) 2001-2003 +# Fraunhofer Institute for Open Communication Systems (FhG Fokus). +# All rights reserved. +# +# Author: Harti Brandt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Begemot: bsnmp/snmpd/snmpd.sh,v 1.3 2004/08/06 08:47:13 brandt Exp $ +# +# SNMPd startup script +# +SNMPD=/usr/local/bin/bsnmpd +PID=/var/run/snmpd.pid +CONF=/etc/snmpd.conf + +case "$1" in + +start) + if [ -r ${PID} ] ; then + if kill -0 `cat ${PID}` ; then + echo "snmpd already running -- pid `cat ${PID}`" >/dev/stderr + exit 1 + fi + rm -f ${PID} + fi + if ${SNMPD} -c ${CONF} -p ${PID} ; then + echo "snmpd started" + fi + ;; + +stop) + if [ -r ${PID} ] ; then + if kill -0 `cat ${PID}` ; then + if kill -15 `cat ${PID}` ; then + echo "snmpd stopped" + exit 0 + fi + echo "cannot kill snmpd" >/dev/stderr + exit 1 + fi + echo "stale pid file -- removing" >/dev/stderr + rm -f ${PID} + exit 1 + fi + echo "snmpd not running" >/dev/stderr + ;; + +status) + if [ ! -r ${PID} ] ; then + echo "snmpd not running" + elif kill -0 `cat ${PID}` ; then + echo "snmpd pid `cat ${PID}`" + else + echo "stale pid file -- pid `cat ${PID}`" + fi + ;; + +*) + echo "usage: `basename $0` {start|stop|status}" + exit 1 +esac + +exit 0 Property changes on: vendor/bsnmp/1.13/snmpd/snmpd.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/snmpmod.3 =================================================================== --- vendor/bsnmp/1.13/snmpd/snmpmod.3 (nonexistent) +++ vendor/bsnmp/1.13/snmpd/snmpmod.3 (revision 336778) @@ -0,0 +1,1184 @@ +.\" +.\" Copyright (c) 2004-2005 +.\" Hartmut Brandt. +.\" All rights reserved. +.\" Copyright (c) 2001-2003 +.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus). +.\" All rights reserved. +.\" +.\" Author: Harti Brandt +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Begemot: bsnmp/snmpd/snmpmod.3,v 1.14 2005/10/04 13:30:35 brandt_h Exp $ +.\" +.Dd December 19, 2010 +.Dt SNMPMOD 3 +.Os +.Sh NAME +.Nm INSERT_OBJECT_OID_LINK_INDEX , +.Nm INSERT_OBJECT_INT_LINK_INDEX , +.Nm FIND_OBJECT_OID_LINK_INDEX , +.Nm NEXT_OBJECT_OID_LINK_INDEX , +.Nm FIND_OBJECT_INT_LINK_INDEX , +.Nm NEXT_OBJECT_INT_LINK_INDEX , +.Nm INSERT_OBJECT_OID_LINK , +.Nm INSERT_OBJECT_INT_LINK , +.Nm FIND_OBJECT_OID_LINK , +.Nm NEXT_OBJECT_OID_LINK , +.Nm FIND_OBJECT_INT_LINK , +.Nm NEXT_OBJECT_INT_LINK , +.Nm INSERT_OBJECT_OID , +.Nm INSERT_OBJECT_INT , +.Nm FIND_OBJECT_OID , +.Nm FIND_OBJECT_INT , +.Nm NEXT_OBJECT_OID , +.Nm NEXT_OBJECT_INT , +.Nm this_tick , +.Nm start_tick , +.Nm get_ticks , +.Nm systemg , +.Nm comm_define , +.Nm community , +.Nm oid_zeroDotZero , +.Nm oid_usmUnknownEngineIDs , +.Nm oid_usmNotInTimeWindows , +.Nm reqid_allocate , +.Nm reqid_next , +.Nm reqid_base , +.Nm reqid_istype , +.Nm reqid_type , +.Nm timer_start , +.Nm timer_start_repeat , +.Nm timer_stop , +.Nm fd_select , +.Nm fd_deselect , +.Nm fd_suspend , +.Nm fd_resume , +.Nm or_register , +.Nm or_unregister , +.Nm buf_alloc , +.Nm buf_size , +.Nm snmp_input_start , +.Nm snmp_input_finish , +.Nm snmp_output , +.Nm snmp_send_port , +.Nm snmp_send_trap , +.Nm snmp_pdu_auth_access +.Nm string_save , +.Nm string_commit , +.Nm string_rollback , +.Nm string_get , +.Nm string_get_max , +.Nm string_free , +.Nm ip_save , +.Nm ip_rollback , +.Nm ip_commit , +.Nm ip_get , +.Nm oid_save , +.Nm oid_rollback , +.Nm oid_commit , +.Nm oid_get , +.Nm index_decode , +.Nm index_compare , +.Nm index_compare_off , +.Nm index_append , +.Nm index_append_off , +.Nm snmpd_usmstats , +.Nm bsnmpd_get_usm_stats , +.Nm bsnmpd_reset_usm_stats , +.Nm usm_first_user , +.Nm usm_next_user , +.Nm usm_find_user , +.Nm usm_new_user , +.Nm usm_delete_user , +.Nm usm_flush_users , +.Nm usm_user , +.Nm snmpd_target_stat , +.Nm bsnmpd_get_target_stats , +.Nm target_first_address , +.Nm target_next_address , +.Nm target_new_address , +.Nm target_activate_address , +.Nm target_delete_address , +.Nm target_first_param , +.Nm target_next_param , +.Nm target_new_param , +.Nm target_delete_param , +.Nm target_first_notify , +.Nm target_next_notify , +.Nm target_new_notify , +.Nm target_delete_notify , +.Nm target_flush_all , +.Nm target_address , +.Nm target_param , +.Nm target_notify +.Nd "SNMP daemon loadable module interface" +.Sh LIBRARY +Begemot SNMP library +.Pq libbsnmp, -lbsnmp +.Sh SYNOPSIS +.In bsnmp/snmpmod.h +.Fn INSERT_OBJECT_OID_LINK_INDEX "PTR" "LIST" "LINK" "INDEX" +.Fn INSERT_OBJECT_INT_LINK_INDEX "PTR" "LIST" "LINK" "INDEX" +.Fn FIND_OBJECT_OID_LINK_INDEX "LIST" "OID" "SUB" "LINK" "INDEX" +.Fn FIND_OBJECT_INT_LINK_INDEX "LIST" "OID" "SUB" "LINK" "INDEX" +.Fn NEXT_OBJECT_OID_LINK_INDEX "LIST" "OID" "SUB" "LINK" "INDEX" +.Fn NEXT_OBJECT_INT_LINK_INDEX "LIST" "OID" "SUB" "LINK" "INDEX" +.Fn INSERT_OBJECT_OID_LINK "PTR" "LIST" "LINK" +.Fn INSERT_OBJECT_INT_LINK "PTR" "LIST" "LINK" +.Fn FIND_OBJECT_OID_LINK "LIST" "OID" "SUB" "LINK" +.Fn FIND_OBJECT_INT_LINK "LIST" "OID" "SUB" "LINK" +.Fn NEXT_OBJECT_OID_LINK "LIST" "OID" "SUB" "LINK" +.Fn NEXT_OBJECT_INT_LINK "LIST" "OID" "SUB" "LINK" +.Fn INSERT_OBJECT_OID "PTR" "LIST" +.Fn INSERT_OBJECT_INT "PTR" "LIST" +.Fn FIND_OBJECT_OID "LIST" "OID" "SUB" +.Fn FIND_OBJECT_INT "LIST" "OID" "SUB" +.Fn NEXT_OBJECT_OID "LIST" "OID" "SUB" +.Fn NEXT_OBJECT_INT "LIST" "OID" "SUB" +.Vt extern uint64_t this_tick ; +.Vt extern uint64_t start_tick ; +.Ft uint64_t +.Fn get_ticks "void" +.Vt extern struct systemg systemg ; +.Ft u_int +.Fn comm_define "u_int priv" "const char *descr" "struct lmodule *mod" "const char *str" +.Ft const char * +.Fn comm_string "u_int comm" +.Vt extern u_int community ; +.Vt extern const struct asn_oid oid_zeroDotZero ; +.Ft u_int +.Fn reqid_allocate "int size" "struct lmodule *mod" +.Ft int32_t +.Fn reqid_next "u_int type" +.Ft int32_t +.Fn reqid_base "u_int type" +.Ft int +.Fn reqid_istype "int32_t reqid" "u_int type" +.Ft u_int +.Fn reqid_type "int32_t reqid" +.Ft void * +.Fn timer_start "u_int ticks" "void (*func)(void *)" "void *uarg" "struct lmodule *mod" +.Ft void * +.Fn timer_start_repeat "u_int ticks" "u_int repeat_ticks" "void (*func)(void *)" "void *uarg" "struct lmodule *mod" +.Ft void +.Fn timer_stop "void *timer_id" +.Ft void * +.Fn fd_select "int fd" "void (*func)(int, void *)" "void *uarg" "struct lmodule *mod" +.Ft void +.Fn fd_deselect "void *fd_id" +.Ft void +.Fn fd_suspend "void *fd_id" +.Ft int +.Fn fd_resume "void *fd_id" +.Ft u_int +.Fn or_register "const struct asn_oid *oid" "const char *descr" "struct lmodule *mod" +.Ft void +.Fn or_unregister "u_int or_id" +.Ft void * +.Fn buf_alloc "int tx" +.Ft size_t +.Fn buf_size "int tx" +.Ft enum snmpd_input_err +.Fo snmp_input_start +.Fa "const u_char *buf" "size_t len" "const char *source" +.Fa "struct snmp_pdu *pdu" "int32_t *ip" "size_t *pdulen" +.Fc +.Ft enum snmpd_input_err +.Fo snmp_input_finish +.Fa "struct snmp_pdu *pdu" "const u_char *rcvbuf" +.Fa "size_t rcvlen" "u_char *sndbuf" "size_t *sndlen" "const char *source" +.Fa "enum snmpd_input_err ierr" "int32_t ip" "void *data" +.Fc +.Ft void +.Fo snmp_output +.Fa "struct snmp_pdu *pdu" "u_char *sndbuf" "size_t *sndlen" +.Fa "const char *dest" +.Fc +.Ft void +.Fo snmp_send_port +.Fa "void *trans" "const struct asn_oid *port" +.Fa "struct snmp_pdu *pdu" "const struct sockaddr *addr" "socklen_t addrlen" +.Fc +.Ft void +.Fn snmp_send_trap "const struct asn_oid *oid" "..." +.Ft enum snmp_code +.Fn snmp_pdu_auth_access "struct snmp_pdu *pdu" "int32_t *ip" +.Ft int +.Fn string_save "struct snmp_value *val" "struct snmp_context *ctx" "ssize_t req_size" "u_char **strp" +.Ft void +.Fn string_commit "struct snmp_context *ctx" +.Ft void +.Fn string_rollback "struct snmp_context *ctx" "u_char **strp" +.Ft int +.Fn string_get "struct snmp_value *val" "const u_char *str" "ssize_t len" +.Ft int +.Fn string_get_max "struct snmp_value *val" "const u_char *str" "ssize_t len" "size_t maxlen" +.Ft void +.Fn string_free "struct snmp_context *ctx" +.Ft int +.Fn ip_save "struct snmp_value *val" "struct snmp_context *ctx" "u_char *ipa" +.Ft void +.Fn ip_rollback "struct snmp_context *ctx" "u_char *ipa" +.Ft void +.Fn ip_commit "struct snmp_context *ctx" +.Ft int +.Fn ip_get "struct snmp_value *val" "u_char *ipa" +.Ft int +.Fn oid_save "struct snmp_value *val" "struct snmp_context *ctx" "struct asn_oid *oid" +.Ft void +.Fn oid_rollback "struct snmp_context *ctx" "struct asn_oid *oid" +.Ft void +.Fn oid_commit "struct snmp_context *ctx" +.Ft int +.Fn oid_get "struct snmp_value *val" "const struct asn_oid *oid" +.Ft int +.Fn index_decode "const struct asn_oid *oid" "u_int sub" "u_int code" "..." +.Ft int +.Fn index_compare "const struct asn_oid *oid1" "u_int sub" "const struct asn_oid *oid2" +.Ft int +.Fn index_compare_off "const struct asn_oid *oid1" "u_int sub" "const struct asn_oid *oid2" "u_int off" +.Ft void +.Fn index_append "struct asn_oid *dst" "u_int sub" "const struct asn_oid *src" +.Ft void +.Fn index_append_off "struct asn_oid *dst" "u_int sub" "const struct asn_oid *src" "u_int off" +.Vt extern struct snmpd_usmstat snmpd_usmstats ; +.Ft struct snmpd_usmstat * +.Fn bsnmpd_get_usm_stats "void" +.Ft void +.Fn bsnmpd_reset_usm_stats "void" +.Ft struct usm_user * +.Fn usm_first_user "void" +.Ft struct usm_user * +.Fn usm_next_user "struct usm_user *uuser" +.Ft struct usm_user * +.Fn usm_find_user "uint8_t *engine" "uint32_t elen" "char *uname" +.Ft struct usm_user * +.Fn usm_new_user "uint8_t *engine" "uint32_t elen" "char *uname" +.Ft void +.Fn usm_delete_user "struct usm_user *" +.Ft void +.Fn usm_flush_users "void" +.Vt extern struct usm_user *usm_user; +.Ft struct snmpd_target_stats * +.Fn bsnmpd_get_target_stats "void" +.Ft struct target_address * +.Fn target_first_address "void" +.Ft struct target_address * +.Fn target_next_address "struct target_address *" +.Ft struct target_address * +.Fn target_new_address "char *" +.Ft int +.Fn target_activate_address "struct target_address *" +.Ft int +.Fn target_delete_address "struct target_address *" +.Ft struct target_param * +.Fn target_first_param "void" +.Ft struct target_param * +.Fn target_next_param "struct target_param *" +.Ft struct target_param * +.Fn target_new_param "char *" +.Ft int +.Fn target_delete_param "struct target_param *" +.Ft struct target_notify * +.Fn target_first_notify "void" +.Ft struct target_notify * +.Fn target_next_notify "struct target_notify *" +.Ft struct target_notify * +.Fn target_new_notify "char *" +.Ft int +.Fn target_delete_notify "struct target_notify *" +.Ft void +.Fn target_flush_all "void" +.Vt extern const struct asn_oid oid_usmUnknownEngineIDs; +.Vt extern const struct asn_oid oid_usmNotInTimeWindows; +.Sh DESCRIPTION +The +.Xr bsnmpd 1 +SNMP daemon implements a minimal MIB which consists of the system group, part +of the SNMP MIB, a private configuration MIB, a trap destination table, a +UDP port table, a community table, a module table, a statistics group and +a debugging group. +All other MIBs are support through loadable modules. +This allows +.Xr bsnmpd 1 +to use for task, that are not the classical SNMP task. +.Ss MODULE LOADING AND UNLOADING +Modules are loaded by writing to the module table. +This table is indexed by a string, that identifies the module to the daemon. +This identifier is used +to select the correct configuration section from the configuration files and +to identify resources allocated to this module. +A row in the module table is +created by writing a string of non-zero length to the +.Va begemotSnmpdModulePath +column. +This string must be the complete path to the file containing the module. +A module can be unloaded by writing a zero length string to the path column +of an existing row. +.Pp +Modules may depend on each other an hence must be loaded in the correct order. +The dependencies are listed in the corresponding manual pages. +.Pp +Upon loading a module the SNMP daemon expects the module file to a export +a global symbol +.Va config . +This symbol should be a variable of type +.Vt struct snmp_module : +.Bd -literal -offset indent +typedef enum snmpd_proxy_err (*proxy_err_f)(struct snmp_pdu *, void *, + const struct asn_oid *, const struct sockaddr *, socklen_t, + enum snmpd_input_err, int32_t); + + +struct snmp_module { + const char *comment; + int (*init)(struct lmodule *, int argc, char *argv[]); + int (*fini)(void); + void (*idle)(void); + void (*dump)(void); + void (*config)(void); + void (*start)(void); + proxy_err_f proxy; + const struct snmp_node *tree; + u_int tree_size; + void (*loading)(const struct lmodule *, int); +}; +.Ed +.Pp +This structure must be statically initialized and its fields have the +following functions: +.Bl -tag -width ".It Va tree_size" +.It Va comment +This is a string that will be visible in the module table. +It should give some hint about the function of this module. +.It Va init +This function is called upon loading the module. +The module pointer should +be stored by the module because it is needed in other calls and the +argument vector will contain the arguments to this module from the daemons +command line. +This function should return 0 if everything is ok or an UNIX error code (see +.Xr errno 3 ) . +Once the function returns 0, the +.Va fini +function is called when the module is unloaded. +.It Va fini +The module is unloaded. +This gives the module a chance to free resources that +are not automatically freed. +Be sure to free all memory, because daemons tend to run very long. +This function pointer may be +.Li NULL +if it is not needed. +.It Va idle +If this function pointer is not +.Li NULL , +the function pointed to by it is called whenever the daemon is going +to wait for an event. +Try to avoid using this feature. +.It Va dump +Whenever the daemon receives a +.Li SIGUSR1 +it dumps it internal state via +.Xr syslog 3 . +If the +.Va dump +field is not +.Li NULL +it is called by the daemon to dump the state of the module. +.It Va config +Whenever the daemon receives a +.Li SIGHUP +signal it re-reads its configuration file. +If the +.Va config +field is not +.Li NULL +it is called after reading the configuration file to give the module a chance +to adapt to the new configuration. +.It Va start +If not +.Li NULL +this function is called after successful loading and initializing the module +to start its actual operation. +.It Va proxy +If the daemon receives a PDU and that PDU has a community string whose +community was registered by this module and +.Va proxy +is not +.Li NULL +than this function is called to handle the PDU. +.It Va tree +This is a pointer to the node array for the MIB tree implemented by this module. +.It Va tree_size +This is the number of nodes in +.Va tree . +.It Va loading +If this pointer is not +.Li NULL +it is called whenever another module was loaded or unloaded. +It gets a +pointer to that module and a flag that is 0 for unloading and 1 for loading. +.El +.Pp +When everything is ok, the daemon merges the module's MIB tree into its current +global tree, calls the modules +.Fn init +function. +If this function returns an error, the modules MIB tree is removed from +the global one and the module is unloaded. +If initialization is successful, the modules +.Fn start +function is called. +After it returns the +.Fn loaded +functions of all modules (including the loaded one) are called. +.Pp +When the module is unloaded, its MIB tree is removed from the global one, +the communities, request id ranges, running timers and selected file +descriptors are released, the +.Fn fini +function is called, the module file is unloaded and the +.Fn loaded +functions of all other modules are called. +.Ss IMPLEMENTING TABLES +There are a number of macros designed to help implementing SNMP tables. +A problem while implementing a table is the support for the GETNEXT operator. +The GETNEXT operation has to find out whether, given an arbitrary OID, the +lessest table row, that has an OID higher than the given OID. +The easiest way +to do this is to keep the table as an ordered list of structures each one +of which contains an OID that is the index of the table row. +This allows easy removal, insertion and search. +.Pp +The helper macros assume, that the table is organized as a TAILQ (see +.Xr queue 3 +and each structure contains a +.Vt struct asn_oid +that is used as index. +For simple tables with only a integer or unsigned index, an alternate form +of the macros is available, that presume the existence of an integer or +unsigned field as index field. +.Pp +The macros have name of the form +.Bd -literal -offset indent +{INSERT,FIND,NEXT}_OBJECT_{OID,INT}[_LINK[_INDEX]] +.Ed +.Pp +The +.Fn INSERT_* +macros are used in the SET operation to insert a new table row into the table. +The +.Fn FIND_* +macros are used in the GET operation to find a specific row in the table. +The +.Fn NEXT_* +macros are used in the GETNEXT operation to find the next row in the table. +The last two macros return a pointer to the row structure if a row is found, +.Li NULL +otherwise. +The macros +.Fn *_OBJECT_OID_* +assume the existence of a +.Vt struct asn_oid +that is used as index, the macros +.Fn *_OBJECT_INT_* +assume the existence of an unsigned integer field that is used as index. +.Pp +The macros +.Fn *_INDEX +allow the explicit naming of the index field in the parameter +.Fa INDEX , +whereas the other macros assume that this field is named +.Va index . +The macros +.Fn *_LINK_* +allow the explicit naming of the link field of the tail queues, the others +assume that the link field is named +.Va link . +Explicitly naming the link field may be necessary if the same structures +are held in two or more different tables. +.Pp +The arguments to the macros are as follows: +.Bl -tag -width "INDEX" +.It Fa PTR +A pointer to the new structure to be inserted into the table. +.It Fa LIST +A pointer to the tail queue head. +.It Fa LINK +The name of the link field in the row structure. +.It Fa INDEX +The name of the index field in the row structure. +.It Fa OID +Must point to the +.Va var +field of the +.Fa value +argument to the node operation callback. +This is the OID to search for. +.It Fa SUB +This is the index of the start of the table index in the OID pointed to +by +.Fa OID . +This is usually the same as the +.Fa sub +argument to the node operation callback. +.El +.Ss DAEMON TIMESTAMPS +The variable +.Va this_tick +contains the tick (there are 100 SNMP ticks in a second) when +the current PDU processing was started. +The variable +.Va start_tick +contains the tick when the daemon was started. +The function +.Fn get_ticks +returns the current tick. +The number of ticks since the daemon was started +is +.Bd -literal -offset indent +get_ticks() - start_tick +.Ed +.Ss THE SYSTEM GROUP +The scalar fields of the system group are held in the global variable +.Va systemg : +.Bd -literal -offset indent +struct systemg { + u_char *descr; + struct asn_oid object_id; + u_char *contact; + u_char *name; + u_char *location; + uint32_t services; + uint32_t or_last_change; +}; +.Ed +.Ss COMMUNITIES +The SNMP daemon implements a community table. +On recipte of a request message +the community string in that message is compared to each of the community +strings in that table, if a match is found, the global variable +.Va community +is set to the community identifier for that community. +Community identifiers are unsigned integers. +For the three standard communities there are three constants defined: +.Bd -literal -offset indent +#define COMM_INITIALIZE 0 +#define COMM_READ 1 +#define COMM_WRITE 2 +.Ed +.Pp +.Va community +is set to +.Li COMM_INITIALIZE +while the assignments in the configuration file are processed. +To +.Li COMM_READ +or +.Li COMM_WRITE +when the community strings for the read-write or read-only community are found +in the incoming PDU. +.Pp +Modules can define additional communities. +This may be necessary to provide +transport proxying (a PDU received on one communication link is proxied to +another link) or to implement non-UDP access points to SNMP. +A new community is defined with the function +.Fn comm_define . +It takes the following parameters: +.Bl -tag -width ".It Fa descr" +.It Fa priv +This is an integer identifying the community to the module. +Each module has its own namespace with regard to this parameter. +The community table is indexed with the module name and this identifier. +.It Fa descr +This is a string providing a human readable description of the community. +It is visible in the community table. +.It Fa mod +This is the module defining the community. +.It Fa str +This is the initial community string. +.El +.Pp +The function returns a globally unique community identifier. +If a SNMPv1 or SNMPv2 PDU is +received who's community string matches, this identifier is set into the global +.Va community . +.Pp +The function +.Fn comm_string +returns the current community string for the given community. +.Pp +All communities defined by a module are automatically released when the module +is unloaded. +.Ss THE USER-BASED SECURITY GROUP +The scalar statistics of the USM group are held in the global variable +.Va snmpd_usmstats : +.Bd -literal -offset indent +struct snmpd_usmstat { + uint32_t unsupported_seclevels; + uint32_t not_in_time_windows; + uint32_t unknown_users; + uint32_t unknown_engine_ids; + uint32_t wrong_digests; + uint32_t decrypt_errors; +}; +.Ed +.Fn bsnmpd_get_usm_stats +returns a pointer to the global structure containing the statistics. +.Fn bsnmpd_reset_usm_stats +clears the statistics of the USM group. +.Pp +A global list of configured USM users is maintained by the daemon. +.Bd -literal -offset indent +struct usm_user { + struct snmp_user suser; + uint8_t user_engine_id[SNMP_ENGINE_ID_SIZ]; + uint32_t user_engine_len; + char user_public[SNMP_ADM_STR32_SIZ]; + uint32_t user_public_len; + int32_t status; + int32_t type; + SLIST_ENTRY(usm_user) up; +}; +.Ed +This structure represents an USM user. The daemon only responds to SNMPv3 PDUs +with user credentials matching an USM user entry in its global list. +If a SNMPv3 PDU is received, whose security model is USM, the global +.Va usm_user +is set to point at the user entry that matches the credentials contained in +the PDU. +However, the daemon does not create or remove USM users, it gives an interface +to external loadable module(s) to manage the list. +.Fn usm_new_user +adds an user entry in the list, and +.Fn usm_delete_user +deletes an existing entry from the list. +.Fn usm_flush_users +is used to remove all configured USM users. +.Fn usm_first_user +will return the first user in the list, or +.Li NULL +if the list is empty. +.Fn usm_next_user +will return the next user of a given entry if one exists, or +.Li NULL . +The list is sorted according to the USM user name and Engine ID. +.Fn usm_find_user +returns the USM user entry matching the given +.Fa engine +and +.Fa uname +or +.Li NULL +if an user with the specified name and engine id is not present in the list. +.Ss THE MANAGEMENT TARGET GROUP +The Management Target group holds target address information used when sending +SNMPv3 notifications. +.Pp +The scalar statistics of the Management Target group are held in the global +variable +.Va snmpd_target_stats : +.Bd -literal -offset indent +struct snmpd_target_stats { + uint32_t unavail_contexts; + uint32_t unknown_contexts; +}; +.Ed +.Fn bsnmpd_get_target_stats +returns a pointer to the global structure containing the statistics. +.Pp +Three global lists of configured management target addresses, parameters and +notifications respectively are maintained by the daemon. +.Bd -literal -offset indent +struct target_address { + char name[SNMP_ADM_STR32_SIZ]; + uint8_t address[SNMP_UDP_ADDR_SIZ]; + int32_t timeout; + int32_t retry; + char taglist[SNMP_TAG_SIZ]; + char paramname[SNMP_ADM_STR32_SIZ]; + int32_t type; + int32_t socket; + int32_t status; + SLIST_ENTRY(target_address) ta; +}; +.Ed +This structure represents a SNMPv3 Management Target address. Each time a SNMP +TRAP is send the daemon will send the Trap to all active Management Target +addresses in its global list. +.Bd -literal -offset indent +struct target_param { + char name[SNMP_ADM_STR32_SIZ]; + int32_t mpmodel; + int32_t sec_model; + char secname[SNMP_ADM_STR32_SIZ]; + enum snmp_usm_level sec_level; + int32_t type; + int32_t status; + SLIST_ENTRY(target_param) tp; +}; +.Ed +This structure represents the information used to generate SNMP messages to the +associated SNMPv3 Management Target addresses. +.Bd -literal -offset indent +struct target_notify { + char name[SNMP_ADM_STR32_SIZ]; + char taglist[SNMP_TAG_SIZ]; + int32_t notify_type; + int32_t type; + int32_t status; + SLIST_ENTRY(target_notify) tn; +}; +.Ed +This structure represents Notification Tag entries - SNMP notifications are sent +to the Target address for each entry in the Management Target Address list that +has a tag matching the specified tag in this structure. +.Pp +The daemon does not create or remove entries in the Management Target group +lists, it gives an interface to external loadable module(s) to manage the lists. +.Fn target_new_address +adds a target address entry, and +.Fn target_delete_address +deletes an existing entry from the target address list. +.Fn target_activate_address +creates a socket associated with the target address entry so that SNMP +notifications may actually be send to that target address. +.Fn target_first_address +will return a pointer to the first target address entry in the list, while +.Fn target_next_address +will return a pointer to the next target address of a given entry if one exists. +.Fn target_new_param +adds a target parameters' entry, and +.Fn target_delete_param +deletes an existing entry from the target parameters list. +.Fn target_first_param +will return a pointer to the first target parameters' entry in the list, while +.Fn target_next_param +will return a pointer to the next target parameters of a given entry if one +exists. +.Fn target_new_notify +adds a notification target entry, and +.Fn target_delete_notify +deletes an existing entry from the notification target list. +.Fn target_first_notify +will return a pointer to the first notification target entry in the list, while +.Fn target_next_notify +will return a pointer to the next notification target of a given entry if one +exists. +.Fn target_flush_all +is used to remove all configured data from the three global Management Target +Group lists. +.Ss WELL KNOWN OIDS +The global variable +.Va oid_zeroDotZero +contains the OID 0.0. +The global variables +.Va oid_usmUnknownEngineIDs +.Va oid_usmNotInTimeWindows +contains the OIDs 1.3.6.1.6.3.15.1.1.4.0 and 1.3.6.1.6.3.15.1.1.2.0 used +in the SNMPv3 USM Engine Discovery. +.Ss REQUEST ID RANGES +For modules that implement SNMP client functions besides SNMP agent functions +it may be necessary to identify SNMP requests by their identifier to allow +easier routing of responses to the correct sub-system. +Request id ranges +provide a way to acquire globally non-overlapping sub-ranges of the entire +31-bit id range. +.Pp +A request id range is allocated with +.Fn reqid_allocate . +The arguments are: the size of the range and the module allocating the range. +For example, the call +.Bd -literal -offset indent +id = reqid_allocate(1000, module); +.Ed +.Pp +allocates a range of 1000 request ids. +The function returns the request +id range identifier or 0 if there is not enough identifier space. +The function +.Fn reqid_base +returns the lowest request id in the given range. +.Pp +Request id are allocated starting at the lowest one linear throughout the range. +If the client application may have a lot of outstanding request the range +must be large enough so that an id is not reused until it is really expired. +.Fn reqid_next +returns the sequentially next id in the range. +.Pp +The function +.Fn reqid_istype +checks whether the request id +.Fa reqid +is within the range identified by +.Fa type . +The function +.Fn reqid_type +returns the range identifier for the given +.Fa reqid +or 0 if the request id is in none of the ranges. +.Ss TIMERS +The SNMP daemon supports an arbitrary number of timers with SNMP tick granularity. +The function +.Fn timer_start +arranges for the callback +.Fa func +to be called with the argument +.Fa uarg +after +.Fa ticks +SNMP ticks have expired. +.Fa mod +is the module that starts the timer. +These timers are one-shot, they are not restarted. +Repeatable timers are started with +.Fn timer_start_repeat +which takes an additional argument +.Fa repeat_ticks . +The argument +.Fa ticks +gives the number of ticks until the first execution of the callback, while +.Fa repeat_ticks +is the number of ticks between invocations of the callback. +Note, that currently the number of initial ticks silently may be set identical +to the number of ticks between callback invocations. +The function returns a timer identifier that can be used to stop the timer via +.Fn timer_stop . +If a module is unloaded all timers started by the module that have not expired +yet are stopped. +.Ss FILE DESCRIPTOR SUPPORT +A module may need to get input from socket file descriptors without blocking +the daemon (for example to implement alternative SNMP transports). +.Pp +The function +.Fn fd_select +causes the callback function +.Fa func +to be called with the file descriptor +.Fa fd +and the user argument +.Fa uarg +whenever the file descriptor +.Fa fd +can be read or has a close condition. +If the file descriptor is not in +non-blocking mode, it is set to non-blocking mode. +If the callback is not needed anymore, +.Fn fd_deselect +may be called with the value returned from +.Fn fd_select . +All file descriptors selected by a module are automatically deselected when +the module is unloaded. +.Pp +To temporarily suspend the file descriptor registration +.Fn fd_suspend +can be called. +This also causes the file descriptor to be switched back to +blocking mode if it was blocking prior the call to +.Fn fd_select . +This is necessary to do synchronous input on a selected socket. +The effect of +.Fn fd_suspend +can be undone with +.Fn fd_resume . +.Ss OBJECT RESOURCES +The system group contains an object resource table. +A module may create an entry in this table by calling +.Fn or_register +with the +.Fa oid +to be registered, a textual description in +.Fa str +and a pointer to the module +.Fa mod . +The registration can be removed with +.Fn or_unregister . +All registrations of a module are automatically removed if the module is +unloaded. +.Ss TRANSMIT AND RECEIVE BUFFERS +A buffer is allocated via +.Fn buf_alloc . +The argument must be 1 for transmit and 0 for receive buffers. +The function may return +.Li NULL +if there is no memory available. +The current buffersize can be obtained with +.Fn buf_size . +.Sh PROCESSING PDUS +For modules that need to do their own PDU processing (for example for proxying) +the following functions are available: +.Pp +Function +.Fn snmp_input_start +decodes the PDU, searches the community, and sets the global +.Va this_tick . +It returns one of the following error codes: +.Bl -tag -width ".It Er SNMPD_INPUT_VALBADLEN" +.It Er SNMPD_INPUT_OK +Everything ok, continue with processing. +.It Er SNMPD_INPUT_FAILED +The PDU could not be decoded, has a wrong version or an unknown +community string. +.It Er SNMPD_INPUT_VALBADLEN +A SET PDU had a value field in a binding with a wrong length field in an +ASN.1 header. +.It Er SNMPD_INPUT_VALRANGE +A SET PDU had a value field in a binding with a value that is out of range +for the given ASN.1 type. +.It Er SNMPD_INPUT_VALBADENC +A SET PDU had a value field in a binding with wrong ASN.1 encoding. +.It Er SNMPD_INPUT_TRUNC +The buffer appears to contain a valid begin of a PDU, but is too short. +For streaming transports this means that the caller must save what he +already has and trying to obtain more input and reissue this input to +the function. +For datagram transports this means that part of the +datagram was lost and the input should be ignored. +.El +.Pp +The function +.Fn snmp_input_finish +does the other half of processing: if +.Fn snmp_input_start +did not return OK, tries to construct an error response. +If the start was OK, it calls the correct function from +.Xr bsnmpagent 3 +to execute the request and depending on the outcome constructs a response or +error response PDU or ignores the request PDU. +It returns either +.Er SNMPD_INPUT_OK +or +.Er SNMPD_INPUT_FAILED . +In the first case a response PDU was constructed and should be sent. +.Pp +The function +.Fn snmp_output +takes a PDU and encodes it. +.Pp +The function +.Fn snmp_send_port +takes a PDU, encodes it and sends it through the given port (identified by +the transport and the index in the port table) to the given address. +.Pp +The function +.Fn snmp_send_trap +sends a trap to all trap destinations. +The arguments are the +.Fa oid +identifying the trap and a NULL-terminated list of +.Vt struct snmp_value +pointers that are to be inserted into the trap binding list. +.Fn snmp_pdu_auth_access +verifies whether access to the object IDs contained in the +.Fa pdu + should be granted or denied, according to the configured View-Based Access +rules. +.Fa ip +contains the index of the first varbinding to which access was denied, or 0 if +access to all varbindings in the PDU is granted. +.Ss SIMPLE ACTION SUPPORT +For simple scalar variables that need no dependencies a number of support +functions is available to handle the set, commit, rollback and get. +.Pp +The following functions are used for OCTET STRING scalars, either NUL terminated +or not: +.Bl -tag -width "XXXXXXXXX" +.It Fn string_save +should be called for SNMP_OP_SET. +.Fa value +and +.Fa ctx +are the resp\&.\& arguments to the node callback. +.Fa valp +is a pointer to the pointer that holds the current value and +.Fa req_size +should be -1 if any size of the string is acceptable or a number larger or +equal zero if the string must have a specific size. +The function saves +the old value in the scratch area (note, that any initial value must have +been allocated by +.Xr malloc 3 ) , +allocates a new string, copies over the new value, NUL-terminates it and +sets the new current value. +.It Fn string_commit +simply frees the saved old value in the scratch area. +.It Fn string_rollback +frees the new value, and puts back the old one. +.It Fn string_get +is used for GET or GETNEXT. +The function +.It Fn string_get_max +can be used instead of +.Fn string_get +to ensure that the returned string has a certain maximum length. +If +.Fa len +is -1, the length is computed via +.Xr strlen 3 +from the current string value. +If the current value is NULL, +a OCTET STRING of zero length is returned. +.It Fn string_free +must be called if either rollback or commit fails to free the saved old value. +.El +.Pp +The following functions are used to process scalars of type IP-address: +.Bl -tag -width "XXXXXXXXX" +.It Fn ip_save +Saves the current value in the scratch area and sets the new value from +.Fa valp . +.It Fn ip_commit +Does nothing. +.It Fn ip_rollback +Restores the old IP address from the scratch area. +.It Fn ip_get +Retrieves the IP current address. +.El +.Pp +The following functions handle OID-typed variables: +.Bl -tag -width "XXXXXXXXX" +.It Fn oid_save +Saves the current value in the scratch area by allocating a +.Vt struct asn_oid +with +.Xr malloc 3 +and sets the new value from +.Fa oid . +.It Fn oid_commit +Frees the old value in the scratch area. +.It Fn oid_rollback +Restores the old OID from the scratch area and frees the old OID. +.It Fn oid_get +Retrieves the OID +.El +.Ss TABLE INDEX HANDLING +The following functions help in handling table indexes: +.Bl -tag -width "XXXXXXXXX" +.It Fn index_decode +Decodes the index part of the OID. +The parameter +.Fa oid +must be a pointer to the +.Va var +field of the +.Fa value +argument of the node callback. +The +.Fa sub +argument must be the index of the start of the index in the OID (this is +the +.Fa sub +argument to the node callback). +.Fa code +is the index expression (parameter +.Fa idx +to the node callback). +These parameters are followed by parameters depending on the syntax of the index +elements as follows: +.Bl -tag -width ".It Li OCTET STRING" +.It Li INTEGER +.Vt int32_t * +expected as argument. +.It Li COUNTER64 +.Vt uint64_t * +expected as argument. +Note, that this syntax is illegal for indexes. +.It Li OCTET STRING +A +.Vt u_char ** +and a +.Vt size_t * +expected as arguments. +A buffer is allocated to hold the decoded string. +.It Li OID +A +.Vt struct asn_oid * +is expected as argument. +.It Li IP ADDRESS +A +.Vt u_int8_t * +expected as argument that points to a buffer of at least four byte. +.It Li COUNTER, GAUGE, TIMETICKS +A +.Vt u_int32_t +expected. +.It Li NULL +No argument expected. +.El +.It Fn index_compare +compares the current variable with an OID. +.Fa oid1 +and +.Fa sub +come from the node callback arguments +.Fa value->var +and +.Fa sub +resp. +.Fa oid2 +is the OID to compare to. +The function returns -1, 0, +1 when the +variable is lesser, equal, higher to the given OID. +.Fa oid2 +must contain only the index part of the table column. +.It Fn index_compare_off +is equivalent to +.Fn index_compare +except that it takes an additional parameter +.Fa off +that causes it to ignore the first +.Fa off +components of both indexes. +.It Fn index_append +appends OID +.Fa src +beginning at position +.Fa sub +to +.Fa dst . +.It Fn index_append_off +appends OID +.Fa src +beginning at position +.Fa off +to +.Fa dst +beginning at position +.Fa sub ++ +.Fa off . +.El +.Sh SEE ALSO +.Xr gensnmptree 1 , +.Xr bsnmpd 1 , +.Xr bsnmpagent 3 , +.Xr bsnmpclient 3 , +.Xr bsnmplib 3 +.Sh STANDARDS +This implementation conforms to the applicable IETF RFCs and ITU-T +recommendations. +.Sh AUTHORS +.An Hartmut Brandt Aq harti@FreeBSD.org Property changes on: vendor/bsnmp/1.13/snmpd/snmpmod.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/snmpmod.h =================================================================== --- vendor/bsnmp/1.13/snmpd/snmpmod.h (nonexistent) +++ vendor/bsnmp/1.13/snmpd/snmpmod.h (revision 336778) @@ -0,0 +1,627 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Copyright (c) 2010 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by Shteryana Sotirova Shopova + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmpd/snmpmod.h,v 1.32 2006/02/14 09:04:20 brandt_h Exp $ + * + * SNMP daemon data and functions exported to modules. + */ +#ifndef snmpmod_h_ +#define snmpmod_h_ + +#include +#include +#include +#include +#include +#include "asn1.h" +#include "snmp.h" +#include "snmpagent.h" + +#define MAX_MOD_ARGS 16 + +/* + * These macros help to handle object lists for SNMP tables. They use + * tail queues to hold the objects in ascending order in the list. + * ordering can be done either on an integer/unsigned field, an asn_oid + * or an ordering function. + */ +#define INSERT_OBJECT_OID_LINK_INDEX(PTR, LIST, LINK, INDEX) do { \ + __typeof (PTR) _lelem; \ + \ + TAILQ_FOREACH(_lelem, (LIST), LINK) \ + if (asn_compare_oid(&_lelem->INDEX, &(PTR)->INDEX) > 0) \ + break; \ + if (_lelem == NULL) \ + TAILQ_INSERT_TAIL((LIST), (PTR), LINK); \ + else \ + TAILQ_INSERT_BEFORE(_lelem, (PTR), LINK); \ + } while (0) + +#define INSERT_OBJECT_INT_LINK_INDEX(PTR, LIST, LINK, INDEX) do { \ + __typeof (PTR) _lelem; \ + \ + TAILQ_FOREACH(_lelem, (LIST), LINK) \ + if ((asn_subid_t)_lelem->INDEX > (asn_subid_t)(PTR)->INDEX)\ + break; \ + if (_lelem == NULL) \ + TAILQ_INSERT_TAIL((LIST), (PTR), LINK); \ + else \ + TAILQ_INSERT_BEFORE(_lelem, (PTR), LINK); \ + } while (0) + +#define INSERT_OBJECT_FUNC_LINK(PTR, LIST, LINK, FUNC) do { \ + __typeof (PTR) _lelem; \ + \ + TAILQ_FOREACH(_lelem, (LIST), LINK) \ + if ((FUNC)(_lelem, (PTR)) > 0) \ + break; \ + if (_lelem == NULL) \ + TAILQ_INSERT_TAIL((LIST), (PTR), LINK); \ + else \ + TAILQ_INSERT_BEFORE(_lelem, (PTR), LINK); \ + } while (0) + +#define INSERT_OBJECT_FUNC_LINK_REV(PTR, LIST, HEAD, LINK, FUNC) do { \ + __typeof (PTR) _lelem; \ + \ + TAILQ_FOREACH_REVERSE(_lelem, (LIST), HEAD, LINK) \ + if ((FUNC)(_lelem, (PTR)) < 0) \ + break; \ + if (_lelem == NULL) \ + TAILQ_INSERT_HEAD((LIST), (PTR), LINK); \ + else \ + TAILQ_INSERT_AFTER((LIST), _lelem, (PTR), LINK); \ + } while (0) + +#define FIND_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({ \ + __typeof (TAILQ_FIRST(LIST)) _lelem; \ + \ + TAILQ_FOREACH(_lelem, (LIST), LINK) \ + if (index_compare(OID, SUB, &_lelem->INDEX) == 0) \ + break; \ + (_lelem); \ + }) + +#define NEXT_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({ \ + __typeof (TAILQ_FIRST(LIST)) _lelem; \ + \ + TAILQ_FOREACH(_lelem, (LIST), LINK) \ + if (index_compare(OID, SUB, &_lelem->INDEX) < 0) \ + break; \ + (_lelem); \ + }) + +#define FIND_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({ \ + __typeof (TAILQ_FIRST(LIST)) _lelem; \ + \ + if ((OID)->len - SUB != 1) \ + _lelem = NULL; \ + else \ + TAILQ_FOREACH(_lelem, (LIST), LINK) \ + if ((OID)->subs[SUB] == (asn_subid_t)_lelem->INDEX)\ + break; \ + (_lelem); \ + }) + +#define NEXT_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({ \ + __typeof (TAILQ_FIRST(LIST)) _lelem; \ + \ + if ((OID)->len - SUB == 0) \ + _lelem = TAILQ_FIRST(LIST); \ + else \ + TAILQ_FOREACH(_lelem, (LIST), LINK) \ + if ((OID)->subs[SUB] < (asn_subid_t)_lelem->INDEX)\ + break; \ + (_lelem); \ + }) + +#define FIND_OBJECT_FUNC_LINK(LIST, OID, SUB, LINK, FUNC) ({ \ + __typeof (TAILQ_FIRST(LIST)) _lelem; \ + \ + TAILQ_FOREACH(_lelem, (LIST), LINK) \ + if ((FUNC)(OID, SUB, _lelem) == 0) \ + break; \ + (_lelem); \ + }) + +#define NEXT_OBJECT_FUNC_LINK(LIST, OID, SUB, LINK, FUNC) ({ \ + __typeof (TAILQ_FIRST(LIST)) _lelem; \ + \ + TAILQ_FOREACH(_lelem, (LIST), LINK) \ + if ((FUNC)(OID, SUB, _lelem) < 0) \ + break; \ + (_lelem); \ + }) + +/* + * Macros for the case where the index field is called 'index' + */ +#define INSERT_OBJECT_OID_LINK(PTR, LIST, LINK) \ + INSERT_OBJECT_OID_LINK_INDEX(PTR, LIST, LINK, index) + +#define INSERT_OBJECT_INT_LINK(PTR, LIST, LINK) do { \ + INSERT_OBJECT_INT_LINK_INDEX(PTR, LIST, LINK, index) + +#define FIND_OBJECT_OID_LINK(LIST, OID, SUB, LINK) \ + FIND_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, index) + +#define NEXT_OBJECT_OID_LINK(LIST, OID, SUB, LINK) \ + NEXT_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, index) + +#define FIND_OBJECT_INT_LINK(LIST, OID, SUB, LINK) \ + FIND_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, index) + +#define NEXT_OBJECT_INT_LINK(LIST, OID, SUB, LINK) \ + NEXT_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, index) + +/* + * Macros for the case where the index field is called 'index' and the + * link field 'link'. + */ +#define INSERT_OBJECT_OID(PTR, LIST) \ + INSERT_OBJECT_OID_LINK_INDEX(PTR, LIST, link, index) + +#define INSERT_OBJECT_INT(PTR, LIST) \ + INSERT_OBJECT_INT_LINK_INDEX(PTR, LIST, link, index) + +#define INSERT_OBJECT_FUNC_REV(PTR, LIST, HEAD, FUNC) \ + INSERT_OBJECT_FUNC_LINK_REV(PTR, LIST, HEAD, link, FUNC) + +#define FIND_OBJECT_OID(LIST, OID, SUB) \ + FIND_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, link, index) + +#define FIND_OBJECT_INT(LIST, OID, SUB) \ + FIND_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, link, index) + +#define FIND_OBJECT_FUNC(LIST, OID, SUB, FUNC) \ + FIND_OBJECT_FUNC_LINK(LIST, OID, SUB, link, FUNC) + +#define NEXT_OBJECT_OID(LIST, OID, SUB) \ + NEXT_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, link, index) + +#define NEXT_OBJECT_INT(LIST, OID, SUB) \ + NEXT_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, link, index) + +#define NEXT_OBJECT_FUNC(LIST, OID, SUB, FUNC) \ + NEXT_OBJECT_FUNC_LINK(LIST, OID, SUB, link, FUNC) + +struct lmodule; + +/* The tick when the program was started. This is the absolute time of + * the start in 100th of a second. */ +extern uint64_t start_tick; + +/* The tick when the current packet was received. This is the absolute + * time in 100th of second. */ +extern uint64_t this_tick; + +/* Get the current absolute time in 100th of a second. */ +uint64_t get_ticks(void); + +/* + * Return code for proxy function + */ +enum snmpd_proxy_err { + /* proxy code will process the PDU */ + SNMPD_PROXY_OK, + /* proxy code does not process PDU */ + SNMPD_PROXY_REJ, + /* drop this PDU */ + SNMPD_PROXY_DROP, + /* drop because of bad community */ + SNMPD_PROXY_BADCOMM, + /* drop because of bad community use */ + SNMPD_PROXY_BADCOMMUSE +}; + +/* + * Input handling + */ +enum snmpd_input_err { + /* proceed with packet */ + SNMPD_INPUT_OK, + /* fatal error in packet, ignore it */ + SNMPD_INPUT_FAILED, + /* value encoding has wrong length in a SET operation */ + SNMPD_INPUT_VALBADLEN, + /* value encoding is out of range */ + SNMPD_INPUT_VALRANGE, + /* value has bad encoding */ + SNMPD_INPUT_VALBADENC, + /* need more data (truncated packet) */ + SNMPD_INPUT_TRUNC, + /* unknown community */ + SNMPD_INPUT_BAD_COMM, +}; + +/* + * Every loadable module must have one of this structures with + * the external name 'config'. + */ +struct snmp_module { + /* a comment describing what this module implements */ + const char *comment; + + /* the initialization function */ + int (*init)(struct lmodule *, int argc, char *argv[]); + + /* the finalisation function */ + int (*fini)(void); + + /* the idle function */ + void (*idle)(void); + + /* the dump function */ + void (*dump)(void); + + /* re-configuration function */ + void (*config)(void); + + /* start operation */ + void (*start)(void); + + /* proxy a PDU */ + enum snmpd_proxy_err (*proxy)(struct snmp_pdu *, void *, + const struct asn_oid *, const struct sockaddr *, socklen_t, + enum snmpd_input_err, int32_t, int); + + /* the tree this module is going to server */ + const struct snmp_node *tree; + u_int tree_size; + + /* function called, when another module was unloaded/loaded */ + void (*loading)(const struct lmodule *, int); +}; + +/* + * Stuff exported to modules + */ + +/* + * The system group. + */ +struct systemg { + u_char *descr; + struct asn_oid object_id; + u_char *contact; + u_char *name; + u_char *location; + uint32_t services; + uint32_t or_last_change; +}; +extern struct systemg systemg; + +/* + * Community support. + * + * We have 2 fixed communities for SNMP read and write access. Modules + * can create their communities dynamically. They are deleted automatically + * if the module is unloaded. + */ +#define COMM_INITIALIZE 0 +#define COMM_READ 1 +#define COMM_WRITE 2 + +u_int comm_define(u_int, const char *descr, struct lmodule *, const char *str); +struct community *comm_define_ordered(u_int priv, const char *descr, + struct asn_oid *index, struct lmodule *owner, const char *str); +const char * comm_string(u_int); + +/* community for current packet */ +extern u_int community; + +/* + * SNMP User-based Security Model data. Modified via the snmp_usm(3) module. + */ +struct snmpd_usmstat { + uint32_t unsupported_seclevels; + uint32_t not_in_time_windows; + uint32_t unknown_users; + uint32_t unknown_engine_ids; + uint32_t wrong_digests; + uint32_t decrypt_errors; +}; + +extern struct snmpd_usmstat snmpd_usmstats; +struct snmpd_usmstat *bsnmpd_get_usm_stats(void); +void bsnmpd_reset_usm_stats(void); + +struct usm_user { + struct snmp_user suser; + uint8_t user_engine_id[SNMP_ENGINE_ID_SIZ]; + uint32_t user_engine_len; + char user_public[SNMP_ADM_STR32_SIZ]; + uint32_t user_public_len; + int32_t status; + int32_t type; + SLIST_ENTRY(usm_user) up; +}; + +SLIST_HEAD(usm_userlist, usm_user); +struct usm_user *usm_first_user(void); +struct usm_user *usm_next_user(struct usm_user *); +struct usm_user *usm_find_user(uint8_t *, uint32_t, char *); +struct usm_user *usm_new_user(uint8_t *, uint32_t, char *); +void usm_delete_user(struct usm_user *); +void usm_flush_users(void); + +/* USM user for current packet */ +extern struct usm_user *usm_user; + +/* + * SNMP View-based Access Control Model data. Modified via the snmp_vacm(3) module. + */ +struct vacm_group; + +struct vacm_user { + /* Security user name from USM */ + char secname[SNMP_ADM_STR32_SIZ]; + int32_t sec_model; + /* Back pointer to user assigned group name */ + struct vacm_group *group; + int32_t type; + int32_t status; + SLIST_ENTRY(vacm_user) vvu; + SLIST_ENTRY(vacm_user) vvg; +}; + +SLIST_HEAD(vacm_userlist, vacm_user); + +struct vacm_group { + char groupname[SNMP_ADM_STR32_SIZ]; + struct vacm_userlist group_users; + SLIST_ENTRY(vacm_group) vge; +}; + +SLIST_HEAD(vacm_grouplist, vacm_group); + +struct vacm_access { + /* The group name is index, not a column in the table */ + struct vacm_group *group; + char ctx_prefix[SNMP_ADM_STR32_SIZ]; + int32_t sec_model; + int32_t sec_level; + int32_t ctx_match; + struct vacm_view *read_view; + struct vacm_view *write_view; + struct vacm_view *notify_view; + int32_t type; + int32_t status; + TAILQ_ENTRY(vacm_access) vva; +}; + +TAILQ_HEAD(vacm_accesslist, vacm_access); + +struct vacm_view { + char viewname[SNMP_ADM_STR32_SIZ]; /* key */ + struct asn_oid subtree; /* key */ + uint8_t mask[16]; + uint8_t exclude; + int32_t type; + int32_t status; + SLIST_ENTRY(vacm_view) vvl; +}; + +SLIST_HEAD(vacm_viewlist, vacm_view); + +struct vacm_context { + /* The ID of the module that registered this context */ + int32_t regid; + char ctxname[SNMP_ADM_STR32_SIZ]; + SLIST_ENTRY(vacm_context) vcl; +}; + +SLIST_HEAD(vacm_contextlist, vacm_context); + +void vacm_groups_init(void); +struct vacm_user *vacm_first_user(void); +struct vacm_user *vacm_next_user(struct vacm_user *); +struct vacm_user *vacm_new_user(int32_t, char *); +int vacm_delete_user(struct vacm_user *); +int vacm_user_set_group(struct vacm_user *, u_char *, u_int); +struct vacm_access *vacm_first_access_rule(void); +struct vacm_access *vacm_next_access_rule(struct vacm_access *); +struct vacm_access *vacm_new_access_rule(char *, char *, int32_t, int32_t); +int vacm_delete_access_rule(struct vacm_access *); +struct vacm_view *vacm_first_view(void); +struct vacm_view *vacm_next_view(struct vacm_view *); +struct vacm_view *vacm_new_view(char *, struct asn_oid *); +int vacm_delete_view(struct vacm_view *); +struct vacm_context *vacm_first_context(void); +struct vacm_context *vacm_next_context(struct vacm_context *); +struct vacm_context *vacm_add_context(char *, int32_t); +void vacm_flush_contexts(int32_t); + +/* + * RFC 3413 SNMP Management Target & Notification MIB + */ + +struct snmpd_target_stats { + uint32_t unavail_contexts; + uint32_t unknown_contexts; +}; + +#define SNMP_UDP_ADDR_SIZ 6 +#define SNMP_TAG_SIZ (255 + 1) + +struct target_address { + char name[SNMP_ADM_STR32_SIZ]; + uint8_t address[SNMP_UDP_ADDR_SIZ]; + int32_t timeout; + int32_t retry; + char taglist[SNMP_TAG_SIZ]; + char paramname[SNMP_ADM_STR32_SIZ]; + int32_t type; + int32_t socket; + int32_t status; + SLIST_ENTRY(target_address) ta; +}; + +SLIST_HEAD(target_addresslist, target_address); + +struct target_param { + char name[SNMP_ADM_STR32_SIZ]; + int32_t mpmodel; + int32_t sec_model; + char secname[SNMP_ADM_STR32_SIZ]; + enum snmp_usm_level sec_level; + int32_t type; + int32_t status; + SLIST_ENTRY(target_param) tp; +}; + +SLIST_HEAD(target_paramlist, target_param); + +struct target_notify { + char name[SNMP_ADM_STR32_SIZ]; + char taglist[SNMP_TAG_SIZ]; + int32_t notify_type; + int32_t type; + int32_t status; + SLIST_ENTRY(target_notify) tn; +}; + +SLIST_HEAD(target_notifylist, target_notify); + +extern struct snmpd_target_stats snmpd_target_stats; +struct snmpd_target_stats *bsnmpd_get_target_stats(void); +struct target_address *target_first_address(void); +struct target_address *target_next_address(struct target_address *); +struct target_address *target_new_address(char *); +int target_activate_address(struct target_address *); +int target_delete_address(struct target_address *); +struct target_param *target_first_param(void); +struct target_param *target_next_param(struct target_param *); +struct target_param *target_new_param(char *); +int target_delete_param(struct target_param *); +struct target_notify *target_first_notify(void); +struct target_notify *target_next_notify(struct target_notify *); +struct target_notify *target_new_notify(char *); +int target_delete_notify (struct target_notify *); +void target_flush_all(void); + +/* + * Well known OIDs + */ +extern const struct asn_oid oid_zeroDotZero; + +/* SNMPv3 Engine Discovery */ +extern const struct asn_oid oid_usmUnknownEngineIDs; +extern const struct asn_oid oid_usmNotInTimeWindows; + +/* + * Request ID ranges. + * + * A module can request a range of request ids and associate them with a + * type field. All ranges are deleted if a module is unloaded. + */ +u_int reqid_allocate(int size, struct lmodule *); +int32_t reqid_next(u_int type); +int32_t reqid_base(u_int type); +int reqid_istype(int32_t reqid, u_int type); +u_int reqid_type(int32_t reqid); + +/* + * Timers. + */ +void *timer_start(u_int, void (*)(void *), void *, struct lmodule *); +void *timer_start_repeat(u_int, u_int, void (*)(void *), void *, + struct lmodule *); +void timer_stop(void *); + +/* + * File descriptors + */ +void *fd_select(int, void (*)(int, void *), void *, struct lmodule *); +void fd_deselect(void *); +void fd_suspend(void *); +int fd_resume(void *); + +/* + * Object resources + */ +u_int or_register(const struct asn_oid *, const char *, struct lmodule *); +void or_unregister(u_int); + +/* + * Buffers + */ +void *buf_alloc(int tx); +size_t buf_size(int tx); + +/* decode PDU and find community */ +enum snmpd_input_err snmp_input_start(const u_char *, size_t, const char *, + struct snmp_pdu *, int32_t *, size_t *); + +/* process the pdu. returns either _OK or _FAILED */ +enum snmpd_input_err snmp_input_finish(struct snmp_pdu *, const u_char *, + size_t, u_char *, size_t *, const char *, enum snmpd_input_err, int32_t, + void *); + +void snmp_output(struct snmp_pdu *, u_char *, size_t *, const char *); +void snmp_send_port(void *, const struct asn_oid *, struct snmp_pdu *, + const struct sockaddr *, socklen_t); +enum snmp_code snmp_pdu_auth_access(struct snmp_pdu *, int32_t *); + +/* sending traps */ +void snmp_send_trap(const struct asn_oid *, ...); + +/* + * Action support + */ +int string_save(struct snmp_value *, struct snmp_context *, ssize_t, u_char **); +void string_commit(struct snmp_context *); +void string_rollback(struct snmp_context *, u_char **); +int string_get(struct snmp_value *, const u_char *, ssize_t); +int string_get_max(struct snmp_value *, const u_char *, ssize_t, size_t); +void string_free(struct snmp_context *); + +int ip_save(struct snmp_value *, struct snmp_context *, u_char *); +void ip_rollback(struct snmp_context *, u_char *); +void ip_commit(struct snmp_context *); +int ip_get(struct snmp_value *, u_char *); + +int oid_save(struct snmp_value *, struct snmp_context *, struct asn_oid *); +void oid_rollback(struct snmp_context *, struct asn_oid *); +void oid_commit(struct snmp_context *); +int oid_get(struct snmp_value *, const struct asn_oid *); + +int index_decode(const struct asn_oid *oid, u_int sub, u_int code, ...); +int index_compare(const struct asn_oid *, u_int, const struct asn_oid *); +int index_compare_off(const struct asn_oid *, u_int, const struct asn_oid *, + u_int); +void index_append(struct asn_oid *, u_int, const struct asn_oid *); +void index_append_off(struct asn_oid *, u_int, const struct asn_oid *, u_int); + +#endif Property changes on: vendor/bsnmp/1.13/snmpd/snmpmod.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/trans_lsock.c =================================================================== --- vendor/bsnmp/1.13/snmpd/trans_lsock.c (nonexistent) +++ vendor/bsnmp/1.13/snmpd/trans_lsock.c (revision 336778) @@ -0,0 +1,669 @@ +/* + * Copyright (c) 2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmpd/trans_lsock.c,v 1.6 2005/02/25 11:50:25 brandt_h Exp $ + * + * Local domain socket transport + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "snmpmod.h" +#include "snmpd.h" +#include "trans_lsock.h" +#include "tree.h" +#include "oid.h" + +static const struct asn_oid + oid_begemotSnmpdLocalPortTable = OIDX_begemotSnmpdLocalPortTable; + +static int lsock_start(void); +static int lsock_stop(int); +static void lsock_close_port(struct tport *); +static int lsock_init_port(struct tport *); +static ssize_t lsock_send(struct tport *, const u_char *, size_t, + const struct sockaddr *, size_t); +static ssize_t lsock_recv(struct tport *, struct port_input *); + +/* exported */ +const struct transport_def lsock_trans = { + "lsock", + OIDX_begemotSnmpdTransLsock, + lsock_start, + lsock_stop, + lsock_close_port, + lsock_init_port, + lsock_send, + lsock_recv +}; +static struct transport *my_trans; + +static int +lsock_remove(struct tport *tp, intptr_t arg __unused) +{ + struct lsock_port *port = (struct lsock_port *)tp; + + (void)remove(port->name); + + return (-1); +} + +static int +lsock_stop(int force) +{ + + if (my_trans != NULL) { + if (!force && trans_first_port(my_trans) != NULL) + return (SNMP_ERR_GENERR); + trans_iter_port(my_trans, lsock_remove, 0); + return (trans_unregister(my_trans)); + } + return (SNMP_ERR_NOERROR); +} + +static int +lsock_start(void) +{ + return (trans_register(&lsock_trans, &my_trans)); +} + +/* + * Open a local port. If this is a datagram socket create also the + * one and only peer. + */ +static int +lsock_open_port(u_char *name, size_t namelen, struct lsock_port **pp, + int type) +{ + struct lsock_port *port; + struct lsock_peer *peer = NULL; + int is_stream, need_cred; + size_t u; + int err; + struct sockaddr_un sa; + + if (namelen == 0 || namelen + 1 > sizeof(sa.sun_path)) + return (SNMP_ERR_BADVALUE); + + switch (type) { + case LOCP_DGRAM_UNPRIV: + is_stream = 0; + need_cred = 0; + break; + + case LOCP_DGRAM_PRIV: + is_stream = 0; + need_cred = 1; + break; + + case LOCP_STREAM_UNPRIV: + is_stream = 1; + need_cred = 0; + break; + + case LOCP_STREAM_PRIV: + is_stream = 1; + need_cred = 1; + break; + + default: + return (SNMP_ERR_BADVALUE); + } + + if ((port = calloc(1, sizeof(*port))) == NULL) + return (SNMP_ERR_GENERR); + + if (!is_stream) { + if ((peer = calloc(1, sizeof(*peer))) == NULL) { + free(port); + return (SNMP_ERR_GENERR); + } + } + if ((port->name = malloc(namelen + 1)) == NULL) { + free(port); + if (!is_stream) + free(peer); + return (SNMP_ERR_GENERR); + } + strncpy(port->name, name, namelen); + port->name[namelen] = '\0'; + + port->type = type; + port->str_sock = -1; + LIST_INIT(&port->peers); + + port->tport.index.len = namelen + 1; + port->tport.index.subs[0] = namelen; + for (u = 0; u < namelen; u++) + port->tport.index.subs[u + 1] = name[u]; + + if (peer != NULL) { + LIST_INSERT_HEAD(&port->peers, peer, link); + + peer->port = port; + + peer->input.fd = -1; + peer->input.id = NULL; + peer->input.stream = is_stream; + peer->input.cred = need_cred; + peer->input.peer = (struct sockaddr *)&peer->peer; + } + + trans_insert_port(my_trans, &port->tport); + + if (community != COMM_INITIALIZE && + (err = lsock_init_port(&port->tport)) != SNMP_ERR_NOERROR) { + lsock_close_port(&port->tport); + return (err); + } + + *pp = port; + + return (SNMP_ERR_NOERROR); +} + +/* + * Close a local domain peer + */ +static void +lsock_peer_close(struct lsock_peer *peer) +{ + + LIST_REMOVE(peer, link); + snmpd_input_close(&peer->input); + free(peer); +} + +/* + * Close a local port + */ +static void +lsock_close_port(struct tport *tp) +{ + struct lsock_port *port = (struct lsock_port *)tp; + struct lsock_peer *peer; + + if (port->str_id != NULL) + fd_deselect(port->str_id); + if (port->str_sock >= 0) + (void)close(port->str_sock); + (void)remove(port->name); + + trans_remove_port(tp); + + while ((peer = LIST_FIRST(&port->peers)) != NULL) + lsock_peer_close(peer); + + free(port->name); + free(port); +} + +/* + * Input on a local socket (either datagram or stream) + */ +static void +lsock_input(int fd __unused, void *udata) +{ + struct lsock_peer *peer = udata; + struct lsock_port *p = peer->port; + + peer->input.peerlen = sizeof(peer->peer); + if (snmpd_input(&peer->input, &p->tport) == -1 && peer->input.stream) + /* framing or other input error */ + lsock_peer_close(peer); +} + +/* + * A UNIX domain listening socket is ready. This means we have a peer + * that we need to accept + */ +static void +lsock_listen_input(int fd, void *udata) +{ + struct lsock_port *p = udata; + struct lsock_peer *peer; + + if ((peer = calloc(1, sizeof(*peer))) == NULL) { + syslog(LOG_WARNING, "%s: peer malloc failed", p->name); + (void)close(accept(fd, NULL, NULL)); + return; + } + + peer->port = p; + + peer->input.stream = 1; + peer->input.cred = (p->type == LOCP_DGRAM_PRIV || + p->type == LOCP_STREAM_PRIV); + peer->input.peerlen = sizeof(peer->peer); + peer->input.peer = (struct sockaddr *)&peer->peer; + + peer->input.fd = accept(fd, peer->input.peer, &peer->input.peerlen); + if (peer->input.fd == -1) { + syslog(LOG_WARNING, "%s: accept failed: %m", p->name); + free(peer); + return; + } + + if ((peer->input.id = fd_select(peer->input.fd, lsock_input, + peer, NULL)) == NULL) { + close(peer->input.fd); + free(peer); + return; + } + + LIST_INSERT_HEAD(&p->peers, peer, link); +} + +/* + * Create a local socket + */ +static int +lsock_init_port(struct tport *tp) +{ + struct lsock_port *p = (struct lsock_port *)tp; + struct sockaddr_un sa; + + if (p->type == LOCP_STREAM_PRIV || p->type == LOCP_STREAM_UNPRIV) { + if ((p->str_sock = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { + syslog(LOG_ERR, "creating local socket: %m"); + return (SNMP_ERR_RES_UNAVAIL); + } + + strlcpy(sa.sun_path, p->name, sizeof(sa.sun_path)); + sa.sun_family = AF_LOCAL; + sa.sun_len = SUN_LEN(&sa); + + (void)remove(p->name); + + if (bind(p->str_sock, (struct sockaddr *)&sa, sizeof(sa))) { + if (errno == EADDRNOTAVAIL) { + close(p->str_sock); + p->str_sock = -1; + return (SNMP_ERR_INCONS_NAME); + } + syslog(LOG_ERR, "bind: %s %m", p->name); + close(p->str_sock); + p->str_sock = -1; + return (SNMP_ERR_GENERR); + } + if (chmod(p->name, 0666) == -1) + syslog(LOG_WARNING, "chmod(%s,0666): %m", p->name); + + if (listen(p->str_sock, 10) == -1) { + syslog(LOG_ERR, "listen: %s %m", p->name); + (void)remove(p->name); + close(p->str_sock); + p->str_sock = -1; + return (SNMP_ERR_GENERR); + } + + p->str_id = fd_select(p->str_sock, lsock_listen_input, p, NULL); + if (p->str_id == NULL) { + (void)remove(p->name); + close(p->str_sock); + p->str_sock = -1; + return (SNMP_ERR_GENERR); + } + } else { + struct lsock_peer *peer; + const int on = 1; + + peer = LIST_FIRST(&p->peers); + + if ((peer->input.fd = socket(PF_LOCAL, SOCK_DGRAM, 0)) < 0) { + syslog(LOG_ERR, "creating local socket: %m"); + return (SNMP_ERR_RES_UNAVAIL); + } + + if (setsockopt(peer->input.fd, 0, LOCAL_CREDS, &on, + sizeof(on)) == -1) { + syslog(LOG_ERR, "setsockopt(LOCAL_CREDS): %m"); + close(peer->input.fd); + peer->input.fd = -1; + return (SNMP_ERR_GENERR); + } + + strlcpy(sa.sun_path, p->name, sizeof(sa.sun_path)); + sa.sun_family = AF_LOCAL; + sa.sun_len = SUN_LEN(&sa); + + (void)remove(p->name); + + if (bind(peer->input.fd, (struct sockaddr *)&sa, sizeof(sa))) { + if (errno == EADDRNOTAVAIL) { + close(peer->input.fd); + peer->input.fd = -1; + return (SNMP_ERR_INCONS_NAME); + } + syslog(LOG_ERR, "bind: %s %m", p->name); + close(peer->input.fd); + peer->input.fd = -1; + return (SNMP_ERR_GENERR); + } + if (chmod(p->name, 0666) == -1) + syslog(LOG_WARNING, "chmod(%s,0666): %m", p->name); + + peer->input.id = fd_select(peer->input.fd, lsock_input, + peer, NULL); + if (peer->input.id == NULL) { + (void)remove(p->name); + close(peer->input.fd); + peer->input.fd = -1; + return (SNMP_ERR_GENERR); + } + } + return (SNMP_ERR_NOERROR); +} + +/* + * Send something + */ +static ssize_t +lsock_send(struct tport *tp, const u_char *buf, size_t len, + const struct sockaddr *addr, size_t addrlen) +{ + struct lsock_port *p = (struct lsock_port *)tp; + struct lsock_peer *peer; + + if (p->type == LOCP_DGRAM_PRIV || p->type == LOCP_DGRAM_UNPRIV) { + peer = LIST_FIRST(&p->peers); + + } else { + /* search for the peer */ + LIST_FOREACH(peer, &p->peers, link) + if (peer->input.peerlen == addrlen && + memcmp(peer->input.peer, addr, addrlen) == 0) + break; + if (peer == NULL) { + errno = ENOTCONN; + return (-1); + } + } + + return (sendto(peer->input.fd, buf, len, 0, addr, addrlen)); +} + +static void +check_priv_stream(struct port_input *pi) +{ + struct xucred ucred; + socklen_t ucredlen; + + /* obtain the accept time credentials */ + ucredlen = sizeof(ucred); + + if (getsockopt(pi->fd, 0, LOCAL_PEERCRED, &ucred, &ucredlen) == 0 && + ucredlen >= sizeof(ucred) && ucred.cr_version == XUCRED_VERSION) + pi->priv = (ucred.cr_uid == 0); + else + pi->priv = 0; +} + +/* + * Receive something + */ +static ssize_t +lsock_recv(struct tport *tp __unused, struct port_input *pi) +{ + struct msghdr msg; + struct iovec iov[1]; + ssize_t len; + + msg.msg_control = NULL; + msg.msg_controllen = 0; + + if (pi->buf == NULL) { + /* no buffer yet - allocate one */ + if ((pi->buf = buf_alloc(0)) == NULL) { + /* ups - could not get buffer. Return an error + * the caller must close the transport. */ + return (-1); + } + pi->buflen = buf_size(0); + pi->consumed = 0; + pi->length = 0; + } + + /* try to get a message */ + msg.msg_name = pi->peer; + msg.msg_namelen = pi->peerlen; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + iov[0].iov_base = pi->buf + pi->length; + iov[0].iov_len = pi->buflen - pi->length; + + len = recvmsg(pi->fd, &msg, 0); + + if (len == -1 || len == 0) + /* receive error */ + return (-1); + + pi->length += len; + + if (pi->cred) + check_priv_stream(pi); + + return (0); +} + +/* + * Dependency to create a lsock port + */ +struct lsock_dep { + struct snmp_dependency dep; + + /* index (path name) */ + u_char *path; + size_t pathlen; + + /* the port */ + struct lsock_port *port; + + /* which of the fields are set */ + u_int set; + + /* type of the port */ + int type; + + /* status */ + int status; +}; +#define LD_TYPE 0x01 +#define LD_STATUS 0x02 +#define LD_CREATE 0x04 /* rollback create */ +#define LD_DELETE 0x08 /* rollback delete */ + +/* + * dependency handler for lsock ports + */ +static int +lsock_func(struct snmp_context *ctx, struct snmp_dependency *dep, + enum snmp_depop op) +{ + struct lsock_dep *ld = (struct lsock_dep *)(void *)dep; + int err = SNMP_ERR_NOERROR; + + switch (op) { + + case SNMP_DEPOP_COMMIT: + if (!(ld->set & LD_STATUS)) + err = SNMP_ERR_BADVALUE; + else if (ld->port == NULL) { + if (!ld->status) + err = SNMP_ERR_BADVALUE; + + else { + /* create */ + err = lsock_open_port(ld->path, ld->pathlen, + &ld->port, ld->type); + if (err == SNMP_ERR_NOERROR) + ld->set |= LD_CREATE; + } + } else if (!ld->status) { + /* delete - hard to roll back so defer to finalizer */ + ld->set |= LD_DELETE; + } else + /* modify - read-only */ + err = SNMP_ERR_READONLY; + + return (err); + + case SNMP_DEPOP_ROLLBACK: + if (ld->set & LD_CREATE) { + /* was create */ + lsock_close_port(&ld->port->tport); + } + return (SNMP_ERR_NOERROR); + + case SNMP_DEPOP_FINISH: + if ((ld->set & LD_DELETE) && ctx->code == SNMP_RET_OK) + lsock_close_port(&ld->port->tport); + free(ld->path); + return (SNMP_ERR_NOERROR); + } + abort(); +} + +/* + * Local port table + */ +int +op_lsock_port(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub-1]; + struct lsock_port *p; + u_char *name; + size_t namelen; + struct lsock_dep *ld; + struct asn_oid didx; + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((p = (struct lsock_port *)trans_next_port(my_trans, + &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &p->tport.index); + break; + + case SNMP_OP_GET: + if ((p = (struct lsock_port *)trans_find_port(my_trans, + &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + p = (struct lsock_port *)trans_find_port(my_trans, + &value->var, sub); + + if (index_decode(&value->var, sub, iidx, &name, &namelen)) + return (SNMP_ERR_NO_CREATION); + + asn_slice_oid(&didx, &value->var, sub, value->var.len); + if ((ld = (struct lsock_dep *)(void *)snmp_dep_lookup(ctx, + &oid_begemotSnmpdLocalPortTable, &didx, sizeof(*ld), + lsock_func)) == NULL) { + free(name); + return (SNMP_ERR_GENERR); + } + + if (ld->path == NULL) { + ld->path = name; + ld->pathlen = namelen; + } else { + free(name); + } + ld->port = p; + + switch (which) { + + case LEAF_begemotSnmpdLocalPortStatus: + if (ld->set & LD_STATUS) + return (SNMP_ERR_INCONS_VALUE); + if (!TRUTH_OK(value->v.integer)) + return (SNMP_ERR_WRONG_VALUE); + + ld->status = TRUTH_GET(value->v.integer); + ld->set |= LD_STATUS; + break; + + case LEAF_begemotSnmpdLocalPortType: + if (ld->set & LD_TYPE) + return (SNMP_ERR_INCONS_VALUE); + if (value->v.integer < 1 || value->v.integer > 4) + return (SNMP_ERR_WRONG_VALUE); + + ld->type = value->v.integer; + ld->set |= LD_TYPE; + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + + default: + abort(); + } + + /* + * Come here to fetch the value + */ + switch (which) { + + case LEAF_begemotSnmpdLocalPortStatus: + value->v.integer = 1; + break; + + case LEAF_begemotSnmpdLocalPortType: + value->v.integer = p->type; + break; + + default: + abort(); + } + + return (SNMP_ERR_NOERROR); +} Property changes on: vendor/bsnmp/1.13/snmpd/trans_lsock.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/trans_lsock.h =================================================================== --- vendor/bsnmp/1.13/snmpd/trans_lsock.h (nonexistent) +++ vendor/bsnmp/1.13/snmpd/trans_lsock.h (revision 336778) @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmpd/trans_lsock.h,v 1.3 2004/08/06 08:47:15 brandt Exp $ + * + * Local domain socket transport + */ + +enum locp { + LOCP_DGRAM_UNPRIV = 1, + LOCP_DGRAM_PRIV = 2, + LOCP_STREAM_UNPRIV = 3, + LOCP_STREAM_PRIV = 4, +}; +struct lsock_peer { + LIST_ENTRY(lsock_peer) link; + struct port_input input; + struct sockaddr_un peer; + struct lsock_port *port; /* parent port */ +}; + +struct lsock_port { + struct tport tport; /* must begin with this */ + + char *name; /* unix path name */ + enum locp type; /* type of port */ + + int str_sock; /* stream socket */ + void *str_id; /* select handle */ + + LIST_HEAD(, lsock_peer) peers; +}; + +extern const struct transport_def lsock_trans; Property changes on: vendor/bsnmp/1.13/snmpd/trans_lsock.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/trans_udp.c =================================================================== --- vendor/bsnmp/1.13/snmpd/trans_udp.c (nonexistent) +++ vendor/bsnmp/1.13/snmpd/trans_udp.c (revision 336778) @@ -0,0 +1,438 @@ +/* + * Copyright (c) 2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmpd/trans_udp.c,v 1.5 2005/10/04 08:46:56 brandt_h Exp $ + * + * UDP transport + */ +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "snmpmod.h" +#include "snmpd.h" +#include "trans_udp.h" +#include "tree.h" +#include "oid.h" + +static int udp_start(void); +static int udp_stop(int); +static void udp_close_port(struct tport *); +static int udp_init_port(struct tport *); +static ssize_t udp_send(struct tport *, const u_char *, size_t, + const struct sockaddr *, size_t); +static ssize_t udp_recv(struct tport *, struct port_input *); + +/* exported */ +const struct transport_def udp_trans = { + "udp", + OIDX_begemotSnmpdTransUdp, + udp_start, + udp_stop, + udp_close_port, + udp_init_port, + udp_send, + udp_recv +}; +static struct transport *my_trans; + +static int +udp_start(void) +{ + return (trans_register(&udp_trans, &my_trans)); +} + +static int +udp_stop(int force __unused) +{ + if (my_trans != NULL) + if (trans_unregister(my_trans) != 0) + return (SNMP_ERR_GENERR); + return (SNMP_ERR_NOERROR); +} + +/* + * A UDP port is ready + */ +static void +udp_input(int fd __unused, void *udata) +{ + struct udp_port *p = udata; + + p->input.peerlen = sizeof(p->ret); + snmpd_input(&p->input, &p->tport); +} + +/* + * Create a UDP socket and bind it to the given port + */ +static int +udp_init_port(struct tport *tp) +{ + struct udp_port *p = (struct udp_port *)tp; + struct sockaddr_in addr; + u_int32_t ip; + const int on = 1; + + if ((p->input.fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { + syslog(LOG_ERR, "creating UDP socket: %m"); + return (SNMP_ERR_RES_UNAVAIL); + } + ip = (p->addr[0] << 24) | (p->addr[1] << 16) | (p->addr[2] << 8) | + p->addr[3]; + memset(&addr, 0, sizeof(addr)); + addr.sin_addr.s_addr = htonl(ip); + addr.sin_port = htons(p->port); + addr.sin_family = AF_INET; + addr.sin_len = sizeof(addr); + if (addr.sin_addr.s_addr == INADDR_ANY) { + if (setsockopt(p->input.fd, IPPROTO_IP, IP_RECVDSTADDR, &on, + sizeof(on)) == -1) { + syslog(LOG_ERR, "setsockopt(IP_RECVDSTADDR): %m"); + close(p->input.fd); + p->input.fd = -1; + return (SNMP_ERR_GENERR); + } + p->recvdstaddr = true; + } + if (bind(p->input.fd, (struct sockaddr *)&addr, sizeof(addr))) { + if (errno == EADDRNOTAVAIL) { + close(p->input.fd); + p->input.fd = -1; + return (SNMP_ERR_INCONS_NAME); + } + syslog(LOG_ERR, "bind: %s:%u %m", inet_ntoa(addr.sin_addr), + p->port); + close(p->input.fd); + p->input.fd = -1; + return (SNMP_ERR_GENERR); + } + if ((p->input.id = fd_select(p->input.fd, udp_input, + p, NULL)) == NULL) { + close(p->input.fd); + p->input.fd = -1; + return (SNMP_ERR_GENERR); + } + return (SNMP_ERR_NOERROR); +} + +/* + * Create a new SNMP Port object and start it, if we are not + * in initialization mode. The arguments are in host byte order. + */ +static int +udp_open_port(u_int8_t *addr, u_int32_t udp_port, struct udp_port **pp) +{ + struct udp_port *port; + int err; + + if (udp_port > 0xffff) + return (SNMP_ERR_NO_CREATION); + if ((port = malloc(sizeof(*port))) == NULL) + return (SNMP_ERR_GENERR); + memset(port, 0, sizeof(*port)); + + /* initialize common part */ + port->tport.index.len = 5; + port->tport.index.subs[0] = addr[0]; + port->tport.index.subs[1] = addr[1]; + port->tport.index.subs[2] = addr[2]; + port->tport.index.subs[3] = addr[3]; + port->tport.index.subs[4] = udp_port; + + port->addr[0] = addr[0]; + port->addr[1] = addr[1]; + port->addr[2] = addr[2]; + port->addr[3] = addr[3]; + port->port = udp_port; + + port->input.fd = -1; + port->input.id = NULL; + port->input.stream = 0; + port->input.cred = 0; + port->input.peer = (struct sockaddr *)&port->ret; + port->input.peerlen = sizeof(port->ret); + + trans_insert_port(my_trans, &port->tport); + + if (community != COMM_INITIALIZE && + (err = udp_init_port(&port->tport)) != SNMP_ERR_NOERROR) { + udp_close_port(&port->tport); + return (err); + } + *pp = port; + return (SNMP_ERR_NOERROR); +} + +/* + * Close an SNMP port + */ +static void +udp_close_port(struct tport *tp) +{ + struct udp_port *port = (struct udp_port *)tp; + + snmpd_input_close(&port->input); + trans_remove_port(tp); + free(port); +} + +/* + * Send something + */ +static ssize_t +udp_send(struct tport *tp, const u_char *buf, size_t len, + const struct sockaddr *addr, size_t addrlen) +{ + struct udp_port *p = (struct udp_port *)tp; + struct cmsghdr *cmsg; + struct msghdr msg; + char cbuf[CMSG_SPACE(sizeof(struct in_addr))]; + struct iovec iov; + + iov.iov_base = __DECONST(void*, buf); + iov.iov_len = len; + + msg.msg_flags = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = __DECONST(void *, addr); + msg.msg_namelen = addrlen; + + if (p->recvdstaddr) { + msg.msg_control = cbuf; + msg.msg_controllen = sizeof(cbuf); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_SENDSRCADDR; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); + memcpy(CMSG_DATA(cmsg), &p->dstaddr, sizeof(struct in_addr)); + } else { + msg.msg_control = NULL; + msg.msg_controllen = 0; + } + + return (sendmsg(p->input.fd, &msg, 0)); +} + +static void +check_priv_dgram(struct port_input *pi, struct sockcred *cred) +{ + + /* process explicitly sends credentials */ + if (cred) + pi->priv = (cred->sc_euid == 0); + else + pi->priv = 0; +} + +/* + * Input from a datagram socket. + * Each receive should return one datagram. + */ +static ssize_t +udp_recv(struct tport *tp, struct port_input *pi) +{ + u_char embuf[1000]; + char cbuf[CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) + + CMSG_SPACE(sizeof(struct in_addr))]; + struct udp_port *p = (struct udp_port *)tp; + struct msghdr msg; + struct iovec iov[1]; + ssize_t len; + struct cmsghdr *cmsg; + struct sockcred *cred = NULL; + + if (pi->buf == NULL) { + /* no buffer yet - allocate one */ + if ((pi->buf = buf_alloc(0)) == NULL) { + /* ups - could not get buffer. Read away input + * and drop it */ + (void)recvfrom(pi->fd, embuf, sizeof(embuf), + 0, NULL, NULL); + /* return error */ + return (-1); + } + pi->buflen = buf_size(0); + } + + /* try to get a message */ + msg.msg_name = pi->peer; + msg.msg_namelen = pi->peerlen; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + memset(cbuf, 0, sizeof(cbuf)); + msg.msg_control = cbuf; + msg.msg_controllen = sizeof(cbuf); + msg.msg_flags = 0; + + iov[0].iov_base = pi->buf; + iov[0].iov_len = pi->buflen; + + len = recvmsg(pi->fd, &msg, 0); + + if (len == -1 || len == 0) + /* receive error */ + return (-1); + + if (msg.msg_flags & MSG_TRUNC) { + /* truncated - drop */ + snmpd_stats.silentDrops++; + snmpd_stats.inTooLong++; + return (-1); + } + + pi->length = (size_t)len; + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level == IPPROTO_IP && + cmsg->cmsg_type == IP_RECVDSTADDR) + memcpy(&p->dstaddr, CMSG_DATA(cmsg), + sizeof(struct in_addr)); + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_CREDS) + cred = (struct sockcred *)(void *)CMSG_DATA(cmsg); + } + + if (pi->cred) + check_priv_dgram(pi, cred); + + return (0); +} + +/* + * Port table + */ +int +op_snmp_port(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub-1]; + struct udp_port *p; + u_int8_t addr[4]; + u_int32_t port; + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((p = (struct udp_port *)trans_next_port(my_trans, + &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &p->tport.index); + break; + + case SNMP_OP_GET: + if ((p = (struct udp_port *)trans_find_port(my_trans, + &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + p = (struct udp_port *)trans_find_port(my_trans, + &value->var, sub); + ctx->scratch->int1 = (p != NULL); + + if (which != LEAF_begemotSnmpdPortStatus) + abort(); + if (!TRUTH_OK(value->v.integer)) + return (SNMP_ERR_WRONG_VALUE); + + ctx->scratch->int2 = TRUTH_GET(value->v.integer); + + if (ctx->scratch->int2) { + /* open an SNMP port */ + if (p != NULL) + /* already open - do nothing */ + return (SNMP_ERR_NOERROR); + + if (index_decode(&value->var, sub, iidx, addr, &port)) + return (SNMP_ERR_NO_CREATION); + return (udp_open_port(addr, port, &p)); + + } else { + /* close SNMP port - do in commit */ + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + p = (struct udp_port *)trans_find_port(my_trans, + &value->var, sub); + if (ctx->scratch->int1 == 0) { + /* did not exist */ + if (ctx->scratch->int2 == 1) { + /* created */ + if (p != NULL) + udp_close_port(&p->tport); + } + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + p = (struct udp_port *)trans_find_port(my_trans, + &value->var, sub); + if (ctx->scratch->int1 == 1) { + /* did exist */ + if (ctx->scratch->int2 == 0) { + /* delete */ + if (p != NULL) + udp_close_port(&p->tport); + } + } + return (SNMP_ERR_NOERROR); + + default: + abort(); + } + + /* + * Come here to fetch the value + */ + switch (which) { + + case LEAF_begemotSnmpdPortStatus: + value->v.integer = 1; + break; + + default: + abort(); + } + + return (SNMP_ERR_NOERROR); +} Property changes on: vendor/bsnmp/1.13/snmpd/trans_udp.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/trans_udp.h =================================================================== --- vendor/bsnmp/1.13/snmpd/trans_udp.h (nonexistent) +++ vendor/bsnmp/1.13/snmpd/trans_udp.h (revision 336778) @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmpd/trans_udp.h,v 1.3 2004/08/06 08:47:16 brandt Exp $ + * + * UDP transport + */ +struct udp_port { + struct tport tport; /* must begin with this */ + + uint8_t addr[4]; /* host byteorder */ + uint16_t port; /* host byteorder */ + + struct port_input input; /* common input stuff */ + + struct sockaddr_in ret; /* the return address */ + + bool recvdstaddr; /* IP_RECVDSTADDR is on */ + struct in_addr dstaddr; /* address the request was sent to */ +}; + +/* argument for open call */ +struct udp_open { + uint8_t addr[4]; /* host byteorder */ + uint16_t port; /* host byteorder */ +}; + +extern const struct transport_def udp_trans; Property changes on: vendor/bsnmp/1.13/snmpd/trans_udp.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/trap.c =================================================================== --- vendor/bsnmp/1.13/snmpd/trap.c (nonexistent) +++ vendor/bsnmp/1.13/snmpd/trap.c (revision 336778) @@ -0,0 +1,910 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Copyright (c) 2010 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by Shteryana Sotirova Shopova + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmpd/trap.c,v 1.9 2005/10/04 11:21:39 brandt_h Exp $ + * + * TrapSinkTable + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "snmpmod.h" +#include "../lib/snmptc.h" +#include "snmpd.h" +#include "tree.h" +#include "oid.h" + +struct trapsink_list trapsink_list = TAILQ_HEAD_INITIALIZER(trapsink_list); + +/* List of target addresses */ +static struct target_addresslist target_addresslist = + SLIST_HEAD_INITIALIZER(target_addresslist); + +/* List of target parameters */ +static struct target_paramlist target_paramlist = + SLIST_HEAD_INITIALIZER(target_paramlist); + +/* List of notification targets */ +static struct target_notifylist target_notifylist = + SLIST_HEAD_INITIALIZER(target_notifylist); + +static const struct asn_oid oid_begemotTrapSinkTable = + OIDX_begemotTrapSinkTable; +static const struct asn_oid oid_sysUpTime = OIDX_sysUpTime; +static const struct asn_oid oid_snmpTrapOID = OIDX_snmpTrapOID; + +struct trapsink_dep { + struct snmp_dependency dep; + u_int set; + u_int status; + u_char comm[SNMP_COMMUNITY_MAXLEN + 1]; + u_int version; + u_int rb; + u_int rb_status; + u_int rb_version; + u_char rb_comm[SNMP_COMMUNITY_MAXLEN + 1]; +}; +enum { + TDEP_STATUS = 0x0001, + TDEP_COMM = 0x0002, + TDEP_VERSION = 0x0004, + + TDEP_CREATE = 0x0001, + TDEP_MODIFY = 0x0002, + TDEP_DESTROY = 0x0004, +}; + +static int +trapsink_create(struct trapsink_dep *tdep) +{ + struct trapsink *t; + struct sockaddr_in sa; + + if ((t = malloc(sizeof(*t))) == NULL) + return (SNMP_ERR_RES_UNAVAIL); + + t->index = tdep->dep.idx; + t->status = TRAPSINK_NOT_READY; + t->comm[0] = '\0'; + t->version = TRAPSINK_V2; + + if ((t->socket = socket(PF_INET, SOCK_DGRAM, 0)) == -1) { + syslog(LOG_ERR, "socket(UDP): %m"); + free(t); + return (SNMP_ERR_RES_UNAVAIL); + } + (void)shutdown(t->socket, SHUT_RD); + memset(&sa, 0, sizeof(sa)); + sa.sin_len = sizeof(sa); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = htonl((t->index.subs[0] << 24) | + (t->index.subs[1] << 16) | (t->index.subs[2] << 8) | + (t->index.subs[3] << 0)); + sa.sin_port = htons(t->index.subs[4]); + + if (connect(t->socket, (struct sockaddr *)&sa, sa.sin_len) == -1) { + syslog(LOG_ERR, "connect(%s,%u): %m", + inet_ntoa(sa.sin_addr), ntohs(sa.sin_port)); + (void)close(t->socket); + free(t); + return (SNMP_ERR_GENERR); + } + + if (tdep->set & TDEP_VERSION) + t->version = tdep->version; + if (tdep->set & TDEP_COMM) + strcpy(t->comm, tdep->comm); + + if (t->comm[0] != '\0') + t->status = TRAPSINK_NOT_IN_SERVICE; + + /* look whether we should activate */ + if (tdep->status == 4) { + if (t->status == TRAPSINK_NOT_READY) { + if (t->socket != -1) + (void)close(t->socket); + free(t); + return (SNMP_ERR_INCONS_VALUE); + } + t->status = TRAPSINK_ACTIVE; + } + + INSERT_OBJECT_OID(t, &trapsink_list); + + tdep->rb |= TDEP_CREATE; + + return (SNMP_ERR_NOERROR); +} + +static void +trapsink_free(struct trapsink *t) +{ + TAILQ_REMOVE(&trapsink_list, t, link); + if (t->socket != -1) + (void)close(t->socket); + free(t); +} + +static int +trapsink_modify(struct trapsink *t, struct trapsink_dep *tdep) +{ + tdep->rb_status = t->status; + tdep->rb_version = t->version; + strcpy(tdep->rb_comm, t->comm); + + if (tdep->set & TDEP_STATUS) { + /* if we are active and should move to not_in_service do + * this first */ + if (tdep->status == 2 && tdep->rb_status == TRAPSINK_ACTIVE) { + t->status = TRAPSINK_NOT_IN_SERVICE; + tdep->rb |= TDEP_MODIFY; + } + } + + if (tdep->set & TDEP_VERSION) + t->version = tdep->version; + if (tdep->set & TDEP_COMM) + strcpy(t->comm, tdep->comm); + + if (tdep->set & TDEP_STATUS) { + /* if we were inactive and should go active - do this now */ + if (tdep->status == 1 && tdep->rb_status != TRAPSINK_ACTIVE) { + if (t->comm[0] == '\0') { + t->status = tdep->rb_status; + t->version = tdep->rb_version; + strcpy(t->comm, tdep->rb_comm); + return (SNMP_ERR_INCONS_VALUE); + } + t->status = TRAPSINK_ACTIVE; + tdep->rb |= TDEP_MODIFY; + } + } + return (SNMP_ERR_NOERROR); +} + +static int +trapsink_unmodify(struct trapsink *t, struct trapsink_dep *tdep) +{ + if (tdep->set & TDEP_STATUS) + t->status = tdep->rb_status; + if (tdep->set & TDEP_VERSION) + t->version = tdep->rb_version; + if (tdep->set & TDEP_COMM) + strcpy(t->comm, tdep->rb_comm); + + return (SNMP_ERR_NOERROR); +} + +static int +trapsink_destroy(struct snmp_context *ctx __unused, struct trapsink *t, + struct trapsink_dep *tdep) +{ + t->status = TRAPSINK_DESTROY; + tdep->rb_status = t->status; + tdep->rb |= TDEP_DESTROY; + return (SNMP_ERR_NOERROR); +} + +static int +trapsink_undestroy(struct trapsink *t, struct trapsink_dep *tdep) +{ + t->status = tdep->rb_status; + return (SNMP_ERR_NOERROR); +} + +static int +trapsink_dep(struct snmp_context *ctx, struct snmp_dependency *dep, + enum snmp_depop op) +{ + struct trapsink_dep *tdep = (struct trapsink_dep *)dep; + struct trapsink *t; + + t = FIND_OBJECT_OID(&trapsink_list, &dep->idx, 0); + + switch (op) { + + case SNMP_DEPOP_COMMIT: + if (tdep->set & TDEP_STATUS) { + switch (tdep->status) { + + case 1: + case 2: + if (t == NULL) + return (SNMP_ERR_INCONS_VALUE); + return (trapsink_modify(t, tdep)); + + case 4: + case 5: + if (t != NULL) + return (SNMP_ERR_INCONS_VALUE); + return (trapsink_create(tdep)); + + case 6: + if (t == NULL) + return (SNMP_ERR_NOERROR); + return (trapsink_destroy(ctx, t, tdep)); + } + } else if (tdep->set != 0) + return (trapsink_modify(t, tdep)); + + return (SNMP_ERR_NOERROR); + + case SNMP_DEPOP_ROLLBACK: + if (tdep->rb & TDEP_CREATE) { + trapsink_free(t); + return (SNMP_ERR_NOERROR); + } + if (tdep->rb & TDEP_MODIFY) + return (trapsink_unmodify(t, tdep)); + if(tdep->rb & TDEP_DESTROY) + return (trapsink_undestroy(t, tdep)); + return (SNMP_ERR_NOERROR); + + case SNMP_DEPOP_FINISH: + if ((tdep->rb & TDEP_DESTROY) && t != NULL && + ctx->code == SNMP_RET_OK) + trapsink_free(t); + return (SNMP_ERR_NOERROR); + } + abort(); +} + +int +op_trapsink(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx, enum snmp_op op) +{ + struct trapsink *t; + u_char ipa[4]; + int32_t port; + struct asn_oid idx; + struct trapsink_dep *tdep; + u_char *p; + + t = NULL; /* gcc */ + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((t = NEXT_OBJECT_OID(&trapsink_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &t->index); + break; + + case SNMP_OP_GET: + if ((t = FIND_OBJECT_OID(&trapsink_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if (index_decode(&value->var, sub, iidx, ipa, &port) || + port == 0 || port > 65535) + return (SNMP_ERR_NO_CREATION); + t = FIND_OBJECT_OID(&trapsink_list, &value->var, sub); + + asn_slice_oid(&idx, &value->var, sub, value->var.len); + + tdep = (struct trapsink_dep *)snmp_dep_lookup(ctx, + &oid_begemotTrapSinkTable, &idx, + sizeof(*tdep), trapsink_dep); + if (tdep == NULL) + return (SNMP_ERR_RES_UNAVAIL); + + switch (value->var.subs[sub - 1]) { + + case LEAF_begemotTrapSinkStatus: + if (tdep->set & TDEP_STATUS) + return (SNMP_ERR_INCONS_VALUE); + switch (value->v.integer) { + + case 1: + case 2: + if (t == NULL) + return (SNMP_ERR_INCONS_VALUE); + break; + + case 4: + case 5: + if (t != NULL) + return (SNMP_ERR_INCONS_VALUE); + break; + + case 6: + break; + + default: + return (SNMP_ERR_WRONG_VALUE); + } + tdep->status = value->v.integer; + tdep->set |= TDEP_STATUS; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotTrapSinkComm: + if (tdep->set & TDEP_COMM) + return (SNMP_ERR_INCONS_VALUE); + if (value->v.octetstring.len == 0 || + value->v.octetstring.len > SNMP_COMMUNITY_MAXLEN) + return (SNMP_ERR_WRONG_VALUE); + for (p = value->v.octetstring.octets; + p < value->v.octetstring.octets + value->v.octetstring.len; + p++) { + if (!isascii(*p) || !isprint(*p)) + return (SNMP_ERR_WRONG_VALUE); + } + tdep->set |= TDEP_COMM; + strncpy(tdep->comm, value->v.octetstring.octets, + value->v.octetstring.len); + tdep->comm[value->v.octetstring.len] = '\0'; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotTrapSinkVersion: + if (tdep->set & TDEP_VERSION) + return (SNMP_ERR_INCONS_VALUE); + if (value->v.integer != TRAPSINK_V1 && + value->v.integer != TRAPSINK_V2) + return (SNMP_ERR_WRONG_VALUE); + tdep->version = value->v.integer; + tdep->set |= TDEP_VERSION; + return (SNMP_ERR_NOERROR); + } + if (t == NULL) + return (SNMP_ERR_INCONS_NAME); + else + return (SNMP_ERR_NOT_WRITEABLE); + + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + } + + switch (value->var.subs[sub - 1]) { + + case LEAF_begemotTrapSinkStatus: + value->v.integer = t->status; + break; + + case LEAF_begemotTrapSinkComm: + return (string_get(value, t->comm, -1)); + + case LEAF_begemotTrapSinkVersion: + value->v.integer = t->version; + break; + + } + return (SNMP_ERR_NOERROR); +} + +static void +snmp_create_v1_trap(struct snmp_pdu *pdu, char *com, + const struct asn_oid *trap_oid) +{ + memset(pdu, 0, sizeof(*pdu)); + strlcpy(pdu->community, com, sizeof(pdu->community)); + + pdu->version = SNMP_V1; + pdu->type = SNMP_PDU_TRAP; + pdu->enterprise = systemg.object_id; + memcpy(pdu->agent_addr, snmpd.trap1addr, 4); + pdu->generic_trap = trap_oid->subs[trap_oid->len - 1] - 1; + pdu->specific_trap = 0; + pdu->time_stamp = get_ticks() - start_tick; + pdu->nbindings = 0; +} + +static void +snmp_create_v2_trap(struct snmp_pdu *pdu, char *com, + const struct asn_oid *trap_oid) +{ + memset(pdu, 0, sizeof(*pdu)); + strlcpy(pdu->community, com, sizeof(pdu->community)); + + pdu->version = SNMP_V2c; + pdu->type = SNMP_PDU_TRAP2; + pdu->request_id = reqid_next(trap_reqid); + pdu->error_index = 0; + pdu->error_status = SNMP_ERR_NOERROR; + + pdu->bindings[0].var = oid_sysUpTime; + pdu->bindings[0].var.subs[pdu->bindings[0].var.len++] = 0; + pdu->bindings[0].syntax = SNMP_SYNTAX_TIMETICKS; + pdu->bindings[0].v.uint32 = get_ticks() - start_tick; + + pdu->bindings[1].var = oid_snmpTrapOID; + pdu->bindings[1].var.subs[pdu->bindings[1].var.len++] = 0; + pdu->bindings[1].syntax = SNMP_SYNTAX_OID; + pdu->bindings[1].v.oid = *trap_oid; + + pdu->nbindings = 2; +} + +static void +snmp_create_v3_trap(struct snmp_pdu *pdu, struct target_param *target, + const struct asn_oid *trap_oid) +{ + struct usm_user *usmuser; + + memset(pdu, 0, sizeof(*pdu)); + + pdu->version = SNMP_V3; + pdu->type = SNMP_PDU_TRAP2; + pdu->request_id = reqid_next(trap_reqid); + pdu->error_index = 0; + pdu->error_status = SNMP_ERR_NOERROR; + + pdu->bindings[0].var = oid_sysUpTime; + pdu->bindings[0].var.subs[pdu->bindings[0].var.len++] = 0; + pdu->bindings[0].syntax = SNMP_SYNTAX_TIMETICKS; + pdu->bindings[0].v.uint32 = get_ticks() - start_tick; + + pdu->bindings[1].var = oid_snmpTrapOID; + pdu->bindings[1].var.subs[pdu->bindings[1].var.len++] = 0; + pdu->bindings[1].syntax = SNMP_SYNTAX_OID; + pdu->bindings[1].v.oid = *trap_oid; + + pdu->nbindings = 2; + + update_snmpd_engine_time(); + + memcpy(pdu->engine.engine_id, snmpd_engine.engine_id, + snmpd_engine.engine_len); + pdu->engine.engine_len = snmpd_engine.engine_len; + pdu->engine.engine_boots = snmpd_engine.engine_boots; + pdu->engine.engine_time = snmpd_engine.engine_time; + pdu->engine.max_msg_size = snmpd_engine.max_msg_size; + strlcpy(pdu->user.sec_name, target->secname, + sizeof(pdu->user.sec_name)); + pdu->security_model = target->sec_model; + + pdu->context_engine_len = snmpd_engine.engine_len; + memcpy(pdu->context_engine, snmpd_engine.engine_id, + snmpd_engine.engine_len); + + if (target->sec_model == SNMP_SECMODEL_USM && + target->sec_level != SNMP_noAuthNoPriv) { + usmuser = usm_find_user(pdu->engine.engine_id, + pdu->engine.engine_len, pdu->user.sec_name); + if (usmuser != NULL) { + pdu->user.auth_proto = usmuser->suser.auth_proto; + pdu->user.priv_proto = usmuser->suser.priv_proto; + memcpy(pdu->user.auth_key, usmuser->suser.auth_key, + sizeof(pdu->user.auth_key)); + memcpy(pdu->user.priv_key, usmuser->suser.priv_key, + sizeof(pdu->user.priv_key)); + } + snmp_pdu_init_secparams(pdu); + } +} + +void +snmp_send_trap(const struct asn_oid *trap_oid, ...) +{ + struct snmp_pdu pdu; + struct trapsink *t; + const struct snmp_value *v; + struct target_notify *n; + struct target_address *ta; + struct target_param *tp; + + va_list ap; + u_char *sndbuf; + char *tag; + size_t sndlen; + ssize_t len; + int32_t ip; + + TAILQ_FOREACH(t, &trapsink_list, link) { + if (t->status != TRAPSINK_ACTIVE) + continue; + + if (t->version == TRAPSINK_V1) + snmp_create_v1_trap(&pdu, t->comm, trap_oid); + else + snmp_create_v2_trap(&pdu, t->comm, trap_oid); + + va_start(ap, trap_oid); + while ((v = va_arg(ap, const struct snmp_value *)) != NULL) + pdu.bindings[pdu.nbindings++] = *v; + va_end(ap); + + if (snmp_pdu_auth_access(&pdu, &ip) != SNMP_CODE_OK) { + syslog(LOG_DEBUG, "send trap to %s failed: no access", + t->comm); + continue; + } + + if ((sndbuf = buf_alloc(1)) == NULL) { + syslog(LOG_ERR, "trap send buffer: %m"); + return; + } + + snmp_output(&pdu, sndbuf, &sndlen, "TRAP"); + + if ((len = send(t->socket, sndbuf, sndlen, 0)) == -1) + syslog(LOG_ERR, "send: %m"); + else if ((size_t)len != sndlen) + syslog(LOG_ERR, "send: short write %zu/%zu", + sndlen, (size_t)len); + + free(sndbuf); + } + + SLIST_FOREACH(n, &target_notifylist, tn) { + if (n->status != RowStatus_active || n->taglist[0] == '\0') + continue; + + SLIST_FOREACH(ta, &target_addresslist, ta) + if ((tag = strstr(ta->taglist, n->taglist)) != NULL && + (tag[strlen(n->taglist)] == ' ' || + tag[strlen(n->taglist)] == '\0' || + tag[strlen(n->taglist)] == '\t' || + tag[strlen(n->taglist)] == '\r' || + tag[strlen(n->taglist)] == '\n') && + ta->status == RowStatus_active) + break; + if (ta == NULL) + continue; + + SLIST_FOREACH(tp, &target_paramlist, tp) + if (strcmp(tp->name, ta->paramname) == 0 && + tp->status == 1) + break; + if (tp == NULL) + continue; + + switch (tp->mpmodel) { + case SNMP_MPM_SNMP_V1: + snmp_create_v1_trap(&pdu, tp->secname, trap_oid); + break; + + case SNMP_MPM_SNMP_V2c: + snmp_create_v2_trap(&pdu, tp->secname, trap_oid); + break; + + case SNMP_MPM_SNMP_V3: + snmp_create_v3_trap(&pdu, tp, trap_oid); + break; + + default: + continue; + } + + va_start(ap, trap_oid); + while ((v = va_arg(ap, const struct snmp_value *)) != NULL) + pdu.bindings[pdu.nbindings++] = *v; + va_end(ap); + + if (snmp_pdu_auth_access(&pdu, &ip) != SNMP_CODE_OK) { + syslog(LOG_DEBUG, "send trap to %s failed: no access", + t->comm); + continue; + } + + if ((sndbuf = buf_alloc(1)) == NULL) { + syslog(LOG_ERR, "trap send buffer: %m"); + return; + } + + snmp_output(&pdu, sndbuf, &sndlen, "TRAP"); + + if ((len = send(ta->socket, sndbuf, sndlen, 0)) == -1) + syslog(LOG_ERR, "send: %m"); + else if ((size_t)len != sndlen) + syslog(LOG_ERR, "send: short write %zu/%zu", + sndlen, (size_t)len); + + free(sndbuf); + } +} + +/* + * RFC 3413 SNMP Management Target MIB + */ +struct snmpd_target_stats * +bsnmpd_get_target_stats(void) +{ + return (&snmpd_target_stats); +} + +struct target_address * +target_first_address(void) +{ + return (SLIST_FIRST(&target_addresslist)); +} + +struct target_address * +target_next_address(struct target_address *addrs) +{ + if (addrs == NULL) + return (NULL); + + return (SLIST_NEXT(addrs, ta)); +} + +struct target_address * +target_new_address(char *aname) +{ + int cmp; + struct target_address *addrs, *temp, *prev; + + SLIST_FOREACH(addrs, &target_addresslist, ta) + if (strcmp(aname, addrs->name) == 0) + return (NULL); + + if ((addrs = (struct target_address *)malloc(sizeof(*addrs))) == NULL) + return (NULL); + + memset(addrs, 0, sizeof(*addrs)); + strlcpy(addrs->name, aname, sizeof(addrs->name)); + addrs->timeout = 150; + addrs->retry = 3; /* XXX */ + + if ((prev = SLIST_FIRST(&target_addresslist)) == NULL || + strcmp(aname, prev->name) < 0) { + SLIST_INSERT_HEAD(&target_addresslist, addrs, ta); + return (addrs); + } + + SLIST_FOREACH(temp, &target_addresslist, ta) { + if ((cmp = strcmp(aname, temp->name)) <= 0) + break; + prev = temp; + } + + if (temp == NULL || cmp < 0) + SLIST_INSERT_AFTER(prev, addrs, ta); + else if (cmp > 0) + SLIST_INSERT_AFTER(temp, addrs, ta); + else { + syslog(LOG_ERR, "Target address %s exists", addrs->name); + free(addrs); + return (NULL); + } + + return (addrs); +} + +int +target_activate_address(struct target_address *addrs) +{ + struct sockaddr_in sa; + + if ((addrs->socket = socket(PF_INET, SOCK_DGRAM, 0)) == -1) { + syslog(LOG_ERR, "socket(UDP): %m"); + return (SNMP_ERR_RES_UNAVAIL); + } + + (void)shutdown(addrs->socket, SHUT_RD); + memset(&sa, 0, sizeof(sa)); + sa.sin_len = sizeof(sa); + sa.sin_family = AF_INET; + + sa.sin_addr.s_addr = htonl((addrs->address[0] << 24) | + (addrs->address[1] << 16) | (addrs->address[2] << 8) | + (addrs->address[3] << 0)); + sa.sin_port = htons(addrs->address[4]) << 8 | + htons(addrs->address[5]) << 0; + + if (connect(addrs->socket, (struct sockaddr *)&sa, sa.sin_len) == -1) { + syslog(LOG_ERR, "connect(%s,%u): %m", + inet_ntoa(sa.sin_addr), ntohs(sa.sin_port)); + (void)close(addrs->socket); + return (SNMP_ERR_GENERR); + } + + addrs->status = RowStatus_active; + + return (SNMP_ERR_NOERROR); +} + +int +target_delete_address(struct target_address *addrs) +{ + SLIST_REMOVE(&target_addresslist, addrs, target_address, ta); + if (addrs->status == RowStatus_active) + close(addrs->socket); + free(addrs); + + return (0); +} + +struct target_param * +target_first_param(void) +{ + return (SLIST_FIRST(&target_paramlist)); +} + +struct target_param * +target_next_param(struct target_param *param) +{ + if (param == NULL) + return (NULL); + + return (SLIST_NEXT(param, tp)); +} + +struct target_param * +target_new_param(char *pname) +{ + int cmp; + struct target_param *param, *temp, *prev; + + SLIST_FOREACH(param, &target_paramlist, tp) + if (strcmp(pname, param->name) == 0) + return (NULL); + + if ((param = (struct target_param *)malloc(sizeof(*param))) == NULL) + return (NULL); + + memset(param, 0, sizeof(*param)); + strlcpy(param->name, pname, sizeof(param->name)); + + if ((prev = SLIST_FIRST(&target_paramlist)) == NULL || + strcmp(pname, prev->name) < 0) { + SLIST_INSERT_HEAD(&target_paramlist, param, tp); + return (param); + } + + SLIST_FOREACH(temp, &target_paramlist, tp) { + if ((cmp = strcmp(pname, temp->name)) <= 0) + break; + prev = temp; + } + + if (temp == NULL || cmp < 0) + SLIST_INSERT_AFTER(prev, param, tp); + else if (cmp > 0) + SLIST_INSERT_AFTER(temp, param, tp); + else { + syslog(LOG_ERR, "Target parameter %s exists", param->name); + free(param); + return (NULL); + } + + return (param); +} + +int +target_delete_param(struct target_param *param) +{ + SLIST_REMOVE(&target_paramlist, param, target_param, tp); + free(param); + + return (0); +} + +struct target_notify * +target_first_notify(void) +{ + return (SLIST_FIRST(&target_notifylist)); +} + +struct target_notify * +target_next_notify(struct target_notify *notify) +{ + if (notify == NULL) + return (NULL); + + return (SLIST_NEXT(notify, tn)); +} + +struct target_notify * +target_new_notify(char *nname) +{ + int cmp; + struct target_notify *notify, *temp, *prev; + + SLIST_FOREACH(notify, &target_notifylist, tn) + if (strcmp(nname, notify->name) == 0) + return (NULL); + + if ((notify = (struct target_notify *)malloc(sizeof(*notify))) == NULL) + return (NULL); + + memset(notify, 0, sizeof(*notify)); + strlcpy(notify->name, nname, sizeof(notify->name)); + + if ((prev = SLIST_FIRST(&target_notifylist)) == NULL || + strcmp(nname, prev->name) < 0) { + SLIST_INSERT_HEAD(&target_notifylist, notify, tn); + return (notify); + } + + SLIST_FOREACH(temp, &target_notifylist, tn) { + if ((cmp = strcmp(nname, temp->name)) <= 0) + break; + prev = temp; + } + + if (temp == NULL || cmp < 0) + SLIST_INSERT_AFTER(prev, notify, tn); + else if (cmp > 0) + SLIST_INSERT_AFTER(temp, notify, tn); + else { + syslog(LOG_ERR, "Notification target %s exists", notify->name); + free(notify); + return (NULL); + } + + return (notify); +} + +int +target_delete_notify(struct target_notify *notify) +{ + SLIST_REMOVE(&target_notifylist, notify, target_notify, tn); + free(notify); + + return (0); +} + +void +target_flush_all(void) +{ + struct target_address *addrs; + struct target_param *param; + struct target_notify *notify; + + while ((addrs = SLIST_FIRST(&target_addresslist)) != NULL) { + SLIST_REMOVE_HEAD(&target_addresslist, ta); + if (addrs->status == RowStatus_active) + close(addrs->socket); + free(addrs); + } + SLIST_INIT(&target_addresslist); + + while ((param = SLIST_FIRST(&target_paramlist)) != NULL) { + SLIST_REMOVE_HEAD(&target_paramlist, tp); + free(param); + } + SLIST_INIT(&target_paramlist); + + while ((notify = SLIST_FIRST(&target_notifylist)) != NULL) { + SLIST_REMOVE_HEAD(&target_notifylist, tn); + free(notify); + } + SLIST_INIT(&target_notifylist); +} Property changes on: vendor/bsnmp/1.13/snmpd/trap.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: vendor/bsnmp/1.13/snmpd/tree.def =================================================================== --- vendor/bsnmp/1.13/snmpd/tree.def (nonexistent) +++ vendor/bsnmp/1.13/snmpd/tree.def (revision 336778) @@ -0,0 +1,214 @@ +# +# Copyright (c) 2001-2003 +# Fraunhofer Institute for Open Communication Systems (FhG Fokus). +# All rights reserved. +# +# Author: Harti Brandt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Begemot: tree.def 517 2006-10-31 08:52:04Z brandt_h $ +# +# System group and private Begemot SNMPd MIB. +# + +include "tc.def" + +(1 internet + (2 mgmt + (1 mibII + (1 system +# +# The standard System group +# + (1 sysDescr OCTETSTRING op_system_group GET) + (2 sysObjectId OID op_system_group GET) + (3 sysUpTime TIMETICKS op_system_group GET) + (4 sysContact OCTETSTRING op_system_group GET SET) + (5 sysName OCTETSTRING op_system_group GET SET) + (6 sysLocation OCTETSTRING op_system_group GET SET) + (7 sysServices INTEGER op_system_group GET) + (8 sysORLastChange TIMETICKS op_system_group GET) + (9 sysORTable + (1 sysOREntry : INTEGER op_or_table + (1 sysORIndex INTEGER) + (2 sysORID OID GET) + (3 sysORDescr OCTETSTRING GET) + (4 sysORUpTime TIMETICKS GET) + )) + ) + (11 snmp + (1 snmpInPkts COUNTER op_snmp GET) + (3 snmpInBadVersions COUNTER op_snmp GET) + (4 snmpInBadCommunityNames COUNTER op_snmp GET) + (5 snmpInBadCommunityUses COUNTER op_snmp GET) + (6 snmpInASNParseErrs COUNTER op_snmp GET) + (30 snmpEnableAuthenTraps INTEGER op_snmp GET SET) + (31 snmpSilentDrops COUNTER op_snmp GET) + (32 snmpProxyDrops COUNTER op_snmp GET) + ) + )) + + (4 private + (1 enterprises +# +# FreeBSD stuff +# + (2238 freeBSD + (4 freeBSDVersion) + ) + +# +# Private Begemot Stuff +# + (12325 fokus + (1 begemot + +# +# Daemon infrastructure +# + (1 begemotSnmpd + (1 begemotSnmpdObjects + +# +# Configuration +# + (1 begemotSnmpdConfig + (1 begemotSnmpdTransmitBuffer INTEGER op_snmpd_config GET SET) + (2 begemotSnmpdReceiveBuffer INTEGER op_snmpd_config GET SET) + (3 begemotSnmpdCommunityDisable INTEGER op_snmpd_config GET SET) + (4 begemotSnmpdTrap1Addr IPADDRESS op_snmpd_config GET SET) + (5 begemotSnmpdVersionEnable UNSIGNED32 op_snmpd_config GET SET) + ) + (2 begemotTrapSinkTable + (1 begemotTrapSinkEntry : IPADDRESS INTEGER op_trapsink + (1 begemotTrapSinkAddr IPADDRESS) + (2 begemotTrapSinkPort INTEGER) + (3 begemotTrapSinkStatus INTEGER GET SET) + (4 begemotTrapSinkComm OCTETSTRING GET SET) + (5 begemotTrapSinkVersion INTEGER GET SET) + ) + ) +# +# Port table +# + (4 begemotSnmpdPortTable + (1 begemotSnmpdPortEntry : IPADDRESS INTEGER op_snmp_port + (1 begemotSnmpdPortAddress IPADDRESS) + (2 begemotSnmpdPortPort UNSIGNED32) + (3 begemotSnmpdPortStatus INTEGER GET SET) + )) +# +# Community table +# + (5 begemotSnmpdCommunityTable + (1 begemotSnmpdCommunityEntry : OCTETSTRING UNSIGNED32 op_community + (1 begemotSnmpdCommunityModule OCTETSTRING) + (2 begemotSnmpdCommunityIndex UNSIGNED32) + (3 begemotSnmpdCommunityString OCTETSTRING GET SET) + (4 begemotSnmpdCommunityDescr OCTETSTRING GET) + (5 begemotSnmpdCommunityPermission INTEGER GET SET) + )) +# +# Module table +# + (6 begemotSnmpdModuleTable + (1 begemotSnmpdModuleEntry : OCTETSTRING op_modules + (1 begemotSnmpdModuleSection OCTETSTRING) + (2 begemotSnmpdModulePath OCTETSTRING GET SET) + (3 begemotSnmpdModuleComment OCTETSTRING GET) + )) +# +# Statistics +# + (7 begemotSnmpdStats + (1 begemotSnmpdStatsNoRxBufs COUNTER op_snmpd_stats GET) + (2 begemotSnmpdStatsNoTxBufs COUNTER op_snmpd_stats GET) + (3 begemotSnmpdStatsInTooLongPkts COUNTER op_snmpd_stats GET) + (4 begemotSnmpdStatsInBadPduTypes COUNTER op_snmpd_stats GET)) +# +# Debugging +# + (8 begemotSnmpdDebug + (1 begemotSnmpdDebugDumpPdus INTEGER op_debug GET SET) + (2 begemotSnmpdDebugSnmpTrace UNSIGNED32 op_debug GET SET) + (3 begemotSnmpdDebugSyslogPri INTEGER op_debug GET SET)) + +# +# Local (UNIX domain) port table +# + (9 begemotSnmpdLocalPortTable + (1 begemotSnmpdLocalPortEntry : OCTETSTRING op_lsock_port + (1 begemotSnmpdLocalPortPath OCTETSTRING) + (2 begemotSnmpdLocalPortStatus INTEGER GET SET) + (3 begemotSnmpdLocalPortType INTEGER GET SET) + )) + + (10 begemotSnmpdTransportMappings + (1 begemotSnmpdTransportTable + (1 begemotSnmpdTransportEntry : OCTETSTRING op_transport_table + (1 begemotSnmpdTransportName OCTETSTRING) + (2 begemotSnmpdTransportStatus INTEGER GET) + (3 begemotSnmpdTransportOid OID GET) + )) + (2 begemotSnmpdTransUdp OID op_transport_dummy) + (3 begemotSnmpdTransLsock OID op_transport_dummy) + ) + ) + (2 begemotSnmpdDefs + (1 begemotSnmpdAgent + (1 begemotSnmpdAgentFreeBSD OID op_dummy) + ) + ) + ) + )) + ) + ) + (6 snmpV2 + (3 snmpModules + (1 snmpMIB + (1 snmpMIBObjects + (4 snmpTrap + (1 snmpTrapOID OID op_snmp_trap) + ) + (5 snmpTraps + (1 coldStart OID op_snmp_trap) + (2 warmStart OID op_snmp_trap) + (5 authenticationFailure OID op_snmp_trap) + ) + (6 snmpSet + (1 snmpSetSerialNo INTEGER op_snmp_set GET SET) + ) + ) + ) + (10 snmpFrameworkMIB + (2 snmpFrameworkMIBObjects + (1 snmpEngine + (1 snmpEngineID OCTETSTRING | SnmpEngineID op_snmp_engine GET) + (2 snmpEngineBoots INTEGER op_snmp_engine GET) + (3 snmpEngineTime INTEGER op_snmp_engine GET) + (4 snmpEngineMaxMessageSize INTEGER op_snmp_engine GET) + ) + ) + ) + )) +) Property changes on: vendor/bsnmp/1.13/snmpd/tree.def ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property