Index: vendor/bsnmp/dist/Makefile.in =================================================================== --- vendor/bsnmp/dist/Makefile.in (revision 359489) +++ vendor/bsnmp/dist/Makefile.in (nonexistent) @@ -1,50 +0,0 @@ -# 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/dist/Makefile.in ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: vendor/bsnmp/dist/config/config.sub =================================================================== --- vendor/bsnmp/dist/config/config.sub (revision 359489) +++ vendor/bsnmp/dist/config/config.sub (nonexistent) @@ -1,1804 +0,0 @@ -#! /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/dist/config/config.sub ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: vendor/bsnmp/dist/config/install-sh =================================================================== --- vendor/bsnmp/dist/config/install-sh (revision 359489) +++ vendor/bsnmp/dist/config/install-sh (nonexistent) @@ -1,527 +0,0 @@ -#!/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/dist/config/install-sh ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: vendor/bsnmp/dist/config/Makefile.pre =================================================================== --- vendor/bsnmp/dist/config/Makefile.pre (revision 359489) +++ vendor/bsnmp/dist/config/Makefile.pre (nonexistent) @@ -1,68 +0,0 @@ -# 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/dist/config/Makefile.pre ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: vendor/bsnmp/dist/config/Makefile.build =================================================================== --- vendor/bsnmp/dist/config/Makefile.build (revision 359489) +++ vendor/bsnmp/dist/config/Makefile.build (nonexistent) @@ -1,11 +0,0 @@ -# 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/dist/config/Makefile.build ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: vendor/bsnmp/dist/config/Makefile.post =================================================================== --- vendor/bsnmp/dist/config/Makefile.post (revision 359489) +++ vendor/bsnmp/dist/config/Makefile.post (nonexistent) @@ -1,129 +0,0 @@ -# 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/dist/config/Makefile.post ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: vendor/bsnmp/dist/config/mkinstalldirs =================================================================== --- vendor/bsnmp/dist/config/mkinstalldirs (revision 359489) +++ vendor/bsnmp/dist/config/mkinstalldirs (nonexistent) @@ -1,40 +0,0 @@ -#! /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/dist/config/mkinstalldirs ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: vendor/bsnmp/dist/config/config.guess =================================================================== --- vendor/bsnmp/dist/config/config.guess (revision 359489) +++ vendor/bsnmp/dist/config/config.guess (nonexistent) @@ -1,1433 +0,0 @@ -#! /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/dist/config/config.guess ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: vendor/bsnmp/dist/config/ltmain.sh =================================================================== --- vendor/bsnmp/dist/config/ltmain.sh (revision 359489) +++ vendor/bsnmp/dist/config/ltmain.sh (nonexistent) @@ -1,11147 +0,0 @@ -#! /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/dist/config/ltmain.sh ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: vendor/bsnmp/dist/configure.ac =================================================================== --- vendor/bsnmp/dist/configure.ac (revision 359489) +++ vendor/bsnmp/dist/configure.ac (nonexistent) @@ -1,202 +0,0 @@ -# -# 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/dist/configure.ac ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: vendor/bsnmp/dist/libbsnmp.pc.in =================================================================== --- vendor/bsnmp/dist/libbsnmp.pc.in (revision 359489) +++ vendor/bsnmp/dist/libbsnmp.pc.in (nonexistent) @@ -1,12 +0,0 @@ -# $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/dist/libbsnmp.pc.in ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: vendor/bsnmp/dist/README.1st =================================================================== --- vendor/bsnmp/dist/README.1st (revision 359489) +++ vendor/bsnmp/dist/README.1st (nonexistent) @@ -1,5 +0,0 @@ -Make the infrastructure: - - libtoolize -c - aclocal - autoconf Property changes on: vendor/bsnmp/dist/README.1st ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: vendor/bsnmp/dist/gensnmpdef/Makefile.in =================================================================== --- vendor/bsnmp/dist/gensnmpdef/Makefile.in (revision 359489) +++ vendor/bsnmp/dist/gensnmpdef/Makefile.in (nonexistent) @@ -1,19 +0,0 @@ -# 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/dist/gensnmpdef/Makefile.in ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: vendor/bsnmp/dist/gensnmptree/Makefile.in =================================================================== --- vendor/bsnmp/dist/gensnmptree/Makefile.in (revision 359489) +++ vendor/bsnmp/dist/gensnmptree/Makefile.in (nonexistent) @@ -1,19 +0,0 @@ -# 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/dist/gensnmptree/Makefile.in ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: vendor/bsnmp/dist/gensnmptree/gensnmptree.1 =================================================================== --- vendor/bsnmp/dist/gensnmptree/gensnmptree.1 (revision 359489) +++ vendor/bsnmp/dist/gensnmptree/gensnmptree.1 (revision 359490) @@ -1,246 +1,252 @@ .\" .\" Copyright (c) 2001-2005 .\" Fraunhofer Institute for Open Communication Systems (FhG Fokus). .\" All rights reserved. -.\" Copyright (c) 2006 +.\" Copyright (c) 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.1 383 2006-05-30 07:40:49Z brandt_h $ .\" -.Dd May 26, 2006 +.Dd April 2, 2019 .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 dEeFfhlt .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 F +emit definitions for C-functions includeable in a C-file that do some basic +stuff on enums like value checking and conversion between value and strings. +.It Fl f +emit definitions for inline C-functions that do some basic +stuff on enums like value checking and conversion between value and strings. .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 Index: vendor/bsnmp/dist/gensnmptree/gensnmptree.c =================================================================== --- vendor/bsnmp/dist/gensnmptree/gensnmptree.c (revision 359489) +++ vendor/bsnmp/dist/gensnmptree/gensnmptree.c (revision 359490) @@ -1,1737 +1,1818 @@ /* * 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\ + -t generate a .def file\n\ "; +/** + * Program operation. + */ +enum op { + /** generate the tree */ + OP_GEN, + + /** extract OIDs */ + OP_EXTRACT, + + /** print the parsed tree */ + OP_TREE, + + /** extract enums */ + OP_ENUMS, +}; + +/** + * Which functions to create. + */ +enum gen_funcs { + /** none */ + GEN_FUNCS_NONE, + + /** functions for header files */ + GEN_FUNCS_H, + + /** functions for C files */ + GEN_FUNCS_C, +}; + /* * 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; + char *subtypes[SNMP_INDEXES_MAX]; } entry; struct leaf { enum snmp_syntax syntax; /* syntax for this leaf */ char *func; /* function name */ + char *subtype; /* subtype */ } leaf; struct column { enum snmp_syntax syntax; /* syntax for this column */ + char *subtype; /* subtype */ } 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) + if ((ptr = calloc(1, 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) +parse_type(enum tok *tok, struct type *t, const char *vname, char **subtype) { u_int syntax; struct enums *e; syntax = val; + if (subtype != NULL) + *subtype = NULL; 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 '|'"); + if (subtype != NULL) + *subtype = savetok(); *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); + char *subtype; + u_int syntax = parse_type(&tok, NULL, node->name, &subtype); if (tok == TOK_STR) { /* LEAF */ node->type = NODE_LEAF; node->u.leaf.func = savetok(); node->u.leaf.syntax = syntax; + node->u.leaf.subtype = subtype; tok = gettoken(); } else { /* COLUMN */ node->type = NODE_COLUMN; node->u.column.syntax = syntax; + node->u.column.subtype = subtype; } 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) + char *subtype; + u_int syntax = parse_type(&tok, NULL, node->name, + &subtype); + if (index_count == SNMP_INDEXES_MAX) report("too many table indexes"); + node->u.entry.subtypes[index_count++] = subtype; 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); + + t->syntax = parse_type(&tok, t, NULL, 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, +gen_node(FILE *fp, const 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) +gen_header(FILE *fp, const 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) +gen_table(FILE *fp, const 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); + if (np->u.leaf.subtype != NULL) + printf(" | %s", np->u.leaf.subtype); 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++) + for (i = 0; i < SNMP_INDEX_COUNT(np->u.entry.index); i++) { print_syntax(SNMP_INDEX(np->u.entry.index, i)); + if (np->u.entry.subtypes[i] != NULL) + printf(" | %s", np->u.entry.subtypes[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); + if (np->u.column.subtype != NULL) + printf(" | %s", np->u.column.subtype); 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 a definition for the enum packed into a guard against multiple + * definitions. + * + * \param fp file to write definition to + * \param t type + * \param dof generate functions too + */ +static void +gen_enum(FILE *fp, const struct type *t, int dof) +{ + 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"); + if (dof) { + fprintf(fp, "#ifdef SNMPENUM_FUNCS\n"); + fprintf(fp, "\n"); + gen_enum_funcs(fp, t, 0); + fprintf(fp, "\n"); + fprintf(fp, "#endif\n"); + fprintf(fp, "\n"); + } + fprintf(fp, "#endif /* %s_defined__ */\n", t->name); +} + +/** * 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) +gen_enums(FILE *fp, int dof) { const struct type *t; LIST_FOREACH(t, &types, link) if (t->is_enum || t->is_bits) - gen_enum(fp, t); + gen_enum(fp, t, dof); } /** * 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); + gen_enum(fp, t, gen_funcs); 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); - } + if (t->is_enum || t->is_bits) + gen_enum(fp, t, gen_funcs); } /** * 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 + * \param gen_funcs which functions to generate */ static void -make_enums(int argc, char *argv[], int gen_funcs_h, int gen_funcs_c) +make_enums(int argc, char *argv[], enum gen_funcs gen_funcs) { - if (gen_funcs_c) { + if (gen_funcs == 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); + extract_all_enums(stdout, gen_funcs == GEN_FUNCS_H); else { for (int i = 0; i < argc; i++) - if (extract_enum(stdout, argv[i], gen_funcs_h)) + if (extract_enum(stdout, argv[i], + gen_funcs == GEN_FUNCS_H)) errx(1, "enum not found: %s", argv[i]); } } } +/** + * Produce the operation tables for the daemon or a module. + * + * \param root tree root + * \param gen_funcs generate enum funcs + */ +static void +make_table(const struct node *root, int gen_funcs) +{ + FILE *fp; + + char fname[MAXPATHLEN + 1]; + 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, gen_funcs); + 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); +} + 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; + enum op op = OP_GEN; + enum gen_funcs gen_funcs = GEN_FUNCS_NONE; + char *infile = NULL; + int opt; while ((opt = getopt(argc, argv, "dEeFfhI:i:lp:t")) != EOF) switch (opt) { case 'd': debug = 1; break; case 'E': - do_enums = 1; + if (op != OP_GEN && op != OP_ENUMS) + errx(1, "-E conflicts with earlier options"); + op = OP_ENUMS; break; case 'e': - do_extract = 1; + if (op != OP_GEN && op != OP_EXTRACT) + errx(1, "-e conflicts with earlier options"); + op = OP_EXTRACT; break; case 'F': - gen_funcs_c = 1; + if (gen_funcs != GEN_FUNCS_NONE && + gen_funcs != GEN_FUNCS_C) + errx(1, "-F conflicts with -f"); + gen_funcs = GEN_FUNCS_C; break; case 'f': - gen_funcs_h = 1; + if (gen_funcs != GEN_FUNCS_NONE && + gen_funcs != GEN_FUNCS_H) + errx(1, "-f conflicts with -F"); + gen_funcs = GEN_FUNCS_H; 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; + if (op != OP_GEN && op != OP_TREE) + errx(1, "-t conflicts with earlier options"); + op = OP_TREE; 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"); + argc -= optind; + argv += optind; - 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"); - + /* open input */ if (infile == NULL) { input_new(stdin, NULL, ""); } else { + FILE *fp; if ((fp = fopen(infile, "r")) == NULL) err(1, "%s", infile); input_new(fp, NULL, infile); } - root = parse_top(gettoken()); + /* parse and check input */ + struct node *root = parse_top(gettoken()); + + int tok; 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++; - } + /* do what the user has requested */ + switch (op) { + + case OP_EXTRACT: + if (argc == 0) + errx(1, "-e requires arguments"); + + for (int i = 0; i < argc; i++) + if (gen_extract(stdout, root, argv[i])) + errx(1, "object not found: %s", argv[i]); return (0); - } - if (do_enums) { - make_enums(argc - optind, argv + optind, - gen_funcs_h, gen_funcs_c); + + case OP_ENUMS: + make_enums(argc, argv, gen_funcs); return (0); - } - if (do_tree) { + + case OP_TREE: + if (argc != 0) + errx(1, "-t allows no arguments"); 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); + case OP_GEN: + if (argc != 0) + errx(1, "tree generation allows no arguments"); + make_table(root, gen_funcs == GEN_FUNCS_H); + return (0); + } } Index: vendor/bsnmp/dist/lib/Makefile.in =================================================================== --- vendor/bsnmp/dist/lib/Makefile.in (revision 359489) +++ vendor/bsnmp/dist/lib/Makefile.in (nonexistent) @@ -1,34 +0,0 @@ -# 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/dist/lib/Makefile.in ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: vendor/bsnmp/dist/lib/snmptc.h.in =================================================================== --- vendor/bsnmp/dist/lib/snmptc.h.in (revision 359489) +++ vendor/bsnmp/dist/lib/snmptc.h.in (nonexistent) @@ -1,65 +0,0 @@ -/*- - * 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/dist/lib/snmptc.h.in ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: vendor/bsnmp/dist/lib/asn1.c =================================================================== --- vendor/bsnmp/dist/lib/asn1.c (revision 359489) +++ vendor/bsnmp/dist/lib/asn1.c (revision 359490) @@ -1,1022 +1,1045 @@ /* * 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)", + if ((*type & ASN_TYPE_MASK) > 0x1e) { + asn_error(b, "tags > 0x1e not supported (%#x)", *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--; } + +#ifdef BOGUS_CVE_2019_5610_FIX + /* + * This is the fix from CVE-2019-5610. + * + * This is the wrong place. Each of the asn functions should check + * that it has enough info for its own work. + */ + if (*len > b->asn_len) { + asn_error(b, "lenen %u exceeding asn_len %u", *len, b->asn_len); + return (ASN_ERR_EOBUF); + } +#endif 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 + * Tags are restricted to one byte tags (value <= 0x1e) 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)", + if ((type & ASN_TYPE_MASK) > 0x1e) { + asn_error(NULL, "types > 0x1e not supported (%#x)", 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) + if (len > 8) { + asn_error(b, "integer too long"); err = ASN_ERR_RANGE; - else if (len > 1 && + } 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; - + *vp = 0; if (b->asn_len < len) { asn_error(b, "truncated integer"); return (ASN_ERR_EOBUF); } if (len == 0) { + /* X.690: 8.3.1 */ 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)) { + if (len > 1 && *b->asn_cptr == 0x00 && (b->asn_cptr[1] & 0x80) == 0) { + /* X.690: 8.3.2 */ + asn_error(b, "non-minimal unsigned"); + b->asn_cptr += len; + b->asn_len -= len; + return (ASN_ERR_BADLEN); + + } + + enum asn_err err = ASN_ERR_OK; + + if ((*b->asn_cptr & 0x80) || len > 9 || + (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; + asn_error(b, "unsigned too large or negative"); + b->asn_cptr += len; + b->asn_len -= len; + return (ASN_ERR_RANGE); } 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) + if (len > 4) { + asn_error(b, "integer too long"); ret = ASN_ERR_BADLEN; - else if (val > INT32_MAX || val < INT32_MIN) + } else if (val > INT32_MAX || val < INT32_MIN) { /* may not happen */ + asn_error(b, "integer out of range"); 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"); + asn_error(b, "OID 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"); + asn_error(NULL, "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)) { + (oid->subs[0] < 2 && oid->subs[1] >= 40) || + (oid->subs[0] == 2 && oid->subs[1] > ASN_MAXID - 2 * 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) { + 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"); } Index: vendor/bsnmp/dist/lib/bsnmpclient.3 =================================================================== --- vendor/bsnmp/dist/lib/bsnmpclient.3 (revision 359489) +++ vendor/bsnmp/dist/lib/bsnmpclient.3 (revision 359490) @@ -1,706 +1,751 @@ .\" .\" 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 +.Dd March 31, 2020 .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. +a UDPv4 socket and for +.Dv SNMP_TRANS_UDP6 +a UDPv6 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), +is the transport name (one of +.Qq udp , +.Qq udp6 , +.Qq stream +or +.Qq 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. +.Pp +The function +.Fn snmp_parse_serverr +fills the transport, the port number and the community strings with +reasonable default values when they are not specified. +The default transport +is +.Dv SNMP_TRANS_UDP . +If the host name contains a slash the default is modified to +.Dv SNMP_TRANS_LOC_DGRAM . +If the host name looks like a numeric IPv6 address the default is +.Dv SNMP_TRANS_UDP6 . +For numeric IPv6 addresses the transport name udp is automatically +translated as +.Dv SNMP_TRANS_UDP6 . +The default port number (for +.Dv udp +or +.Dv udp6 ) +is +.Qq snmp . +The default read community is +.Qq public +and the default write community +.Qq private . +.Pp +.Fn snmp_parse_server +recognizes path names, host names and numerical IPv4 and IPv6 addresses. +A string consisting of digits and periods is assumed to be an IPv4 address +and must be parseable by +.Fn inet_aton 3 . +An IPv6 address is any string enclosed in square brackets. +It must be parseable with +.Fn gethostinfo 3 . +.Pp +The port number for +.Fn snmp_parse_server +can be specified numerically or symbolically. +It is ignored for local sockets. .Sh DIAGNOSTICS -If an error occurs in any of the function an error indication as described +If an error occurs in any of the functions an error indication as described above is returned. -Additionally the function sets a printable error string -in the +Additionally the function sets a printable error string in the .Va error -filed of +field 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 Index: vendor/bsnmp/dist/lib/snmp.h =================================================================== --- vendor/bsnmp/dist/lib/snmp.h (revision 359489) +++ vendor/bsnmp/dist/lib/snmp.h (revision 359490) @@ -1,284 +1,287 @@ /* * 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 BSNMP_MAJOR 1 +#define BSNMP_MINOR 13 + #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 Index: vendor/bsnmp/dist/lib/snmpclient.c =================================================================== --- vendor/bsnmp/dist/lib/snmpclient.c (revision 359489) +++ vendor/bsnmp/dist/lib/snmpclient.c (revision 359490) @@ -1,1964 +1,2298 @@ /* - * Copyright (c) 2004-2005 + * Copyright (c) 2004-2005,2018-2019 * 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 #include #include #include #ifdef HAVE_STDINT_H #include #elif defined(HAVE_INTTYPES_H) #include #endif #include #ifdef HAVE_ERR_H #include #endif +#include + #include "support.h" #include "asn1.h" #include "snmp.h" #include "snmpclient.h" #include "snmppriv.h" +#define DEBUG_PARSE 0 + /* 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) + ((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_family = snmp_client.trans == SNMP_TRANS_UDP ? AF_INET : + AF_INET6; 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: + case SNMP_TRANS_UDP6: 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 +static const char *const trans_list[] = { + [SNMP_TRANS_UDP] = "udp::", + [SNMP_TRANS_LOC_DGRAM] = "dgram::", + [SNMP_TRANS_LOC_STREAM] = "stream::", + [SNMP_TRANS_UDP6] = "udp6::", +}; + +/** + * Try to get a transport identifier which is a leading alphanumeric string + * terminated by a double colon. The string may not be empty. The transport + * identifier is optional. Unknown transport identifiers are reject. + * Be careful: a double colon can also occur in a numeric IPv6 address. * - * [trans::][community@][server][:port] + * \param sc client struct to set errors + * \param strp possible start of transport; updated to point to + * the next character to parse + * + * \return transport identifier */ -int -snmp_parse_server(struct snmp_client *sc, const char *str) +static inline int +get_transp(struct snmp_client *sc, const char **strp) { - const char *p, *s = str; + const char *p; + size_t i; - /* look for a double colon */ - for (p = s; *p != '\0'; p++) { - if (*p == '\\' && p[1] != '\0') { - p++; - continue; + for (i = 0; i < nitems(trans_list); i++) { + p = strstr(*strp, trans_list[i]); + if (p == *strp) { + *strp += strlen(trans_list[i]); + return ((int)i); } - 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; + + p = strstr(*strp, "::"); + if (p == *strp) { + seterr(sc, "empty transport specifier"); + return (-1); } + if (p == NULL) + /* by default assume UDP */ + return (SNMP_TRANS_UDP); - /* look for a @ */ - for (p = s; *p != '\0'; p++) { - if (*p == '\\' && p[1] != '\0') { - p++; - continue; - } - if (*p == '@') - break; + /* ignore :: after [ */ + const char *ob = strchr(*strp, '['); + if (ob != NULL && p > ob) + /* by default assume UDP */ + return (SNMP_TRANS_UDP); + + seterr(sc, "unknown transport specifier '%.*s'", p - *strp, *strp); + return (-1); +} + +/** + * Try to get community string. Eat everything up to the last @ (if there is + * any) but only if it is not longer than SNMP_COMMUNITY_MAXLEN. Empty + * community strings are legal. + * + * \param sc client struct to set errors + * \param strp possible start of community; updated to the point to + * the next character to parse + * + * \return end of community; equals *strp if there is none; NULL if there + * was an error + */ +static inline const char * +get_comm(struct snmp_client *sc, const char **strp) +{ + const char *p = strrchr(*strp, '@'); + + if (p == NULL) + /* no community string */ + return (*strp); + + if (p - *strp > SNMP_COMMUNITY_MAXLEN) { + seterr(sc, "community string too long '%.*s'", + p - *strp, *strp); + return (NULL); } - if (*p != '\0') { - if (p - s > SNMP_COMMUNITY_MAXLEN) { - seterr(sc, "community string too long"); - return (-1); + *strp = p + 1; + return (p); +} + +/** + * Try to get an IPv6 address. This starts with an [ and should end with an ] + * and everything between should be not longer than INET6_ADDRSTRLEN and + * parseable by inet_pton(). + * + * \param sc client struct to set errors + * \param strp possible start of IPv6 address (the '['); updated to point to + * the next character to parse (the one after the closing ']') + * + * \return end of address (equals *strp + 1 if there is none) or NULL + * on errors + */ +static inline const char * +get_ipv6(struct snmp_client *sc, const char **strp) +{ + char str[INET6_ADDRSTRLEN + IF_NAMESIZE]; + struct addrinfo hints, *res; + int error; + + if (**strp != '[') + return (*strp + 1); + + const char *p = *strp + 1; + while (*p != ']' ) { + if (*p == '\0') { + seterr(sc, "unterminated IPv6 address '%.*s'", + p - *strp, *strp); + return (NULL); } - 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; + p++; } - /* look for a colon */ - for (p = s; *p != '\0'; p++) { - if (*p == '\\' && p[1] != '\0') { - p++; - continue; - } - if (*p == ':') - break; + if (p - *strp > INET6_ADDRSTRLEN + IF_NAMESIZE) { + seterr(sc, "IPv6 address too long '%.*s'", p - *strp, *strp); + return (NULL); } - 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); - } + strncpy(str, *strp + 1, p - (*strp + 1)); + str[p - (*strp + 1)] = '\0'; - } else if (p > s) { - /* host */ - free(sc->chost); - if ((sc->chost = strdup(s)) == NULL) { - seterr(sc, "%s", strerror(errno)); + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME | AI_NUMERICHOST; + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + error = getaddrinfo(str, NULL, &hints, &res); + if (error != 0) { + seterr(sc, "%s: %s", str, gai_strerror(error)); + return (NULL); + } + freeaddrinfo(res); + *strp = p + 1; + return (p); +} + +/** + * Try to get an IPv4 address. This starts with a digit and consists of digits + * and dots, is not longer INET_ADDRSTRLEN and must be parseable by + * inet_aton(). + * + * \param sc client struct to set errors + * \param strp possible start of IPv4 address; updated to point to the + * next character to parse + * + * \return end of address (equals *strp if there is none) or NULL + * on errors + */ +static inline const char * +get_ipv4(struct snmp_client *sc, const char **strp) +{ + const char *p = *strp; + + while (isascii(*p) && (isdigit(*p) || *p == '.')) + p++; + + if (p - *strp > INET_ADDRSTRLEN) { + seterr(sc, "IPv4 address too long '%.*s'", p - *strp, *strp); + return (NULL); + } + if (*strp == p) + return *strp; + + char str[INET_ADDRSTRLEN + 1]; + strncpy(str, *strp, p - *strp); + str[p - *strp] = '\0'; + + struct in_addr addr; + if (inet_aton(str, &addr) != 1) { + seterr(sc, "illegal IPv4 address '%s'", str); + return (NULL); + } + + *strp = p; + return (p); +} + +/** + * Try to get a hostname. This includes everything up to but not including + * the last colon (if any). There is no length restriction. + * + * \param sc client struct to set errors + * \param strp possible start of hostname; updated to point to the next + * character to parse (the trailing NUL character or the last + * colon) + * + * \return end of address (equals *strp if there is none) + */ +static inline const char * +get_host(struct snmp_client *sc __unused, const char **strp) +{ + const char *p = strrchr(*strp, ':'); + + if (p == NULL) { + *strp += strlen(*strp); + return (*strp); + } + + *strp = p; + return (p); +} + +/** + * Try to get a port number. This start with a colon and extends to the end + * of string. The port number must not be empty. + * + * \param sc client struct to set errors + * \param strp possible start of port specification; if this points to a + * colon there is a port specification + * + * \return end of port number (equals *strp if there is none); NULL + * if there is no port number + */ +static inline const char * +get_port(struct snmp_client *sc, const char **strp) +{ + if (**strp != ':') + return (*strp + 1); + + if ((*strp)[1] == '\0') { + seterr(sc, "empty port name"); + return (NULL); + } + + *strp += strlen(*strp); + return (*strp); +} + +/** + * Save the string in the range given by two pointers. + * + * \param sc client struct to set errors + * \param s begin and end pointers + * + * \return freshly allocated copy of the string between s[0] and s[1] + */ +static inline char * +save_str(struct snmp_client *sc, const char *const s[2]) +{ + char *m; + + if ((m = malloc(s[1] - s[0] + 1)) == NULL) { + seterr(sc, "%s: %s", __func__, strerror(errno)); + return (NULL); + } + strncpy(m, s[0], s[1] - s[0]); + m[s[1] - s[0]] = '\0'; + + return (m); +} + +/** + * Parse a server specification. All parts are optional: + * + * [::][@][][:] + * + * The transport string consists of letters, digits or '_' and starts with + * a letter or digit. It is terminated by two colons and may not be empty. + * + * The community string is terminated by the last '@' and does not exceed + * SNMP_COMMUNITY_MAXLEN. It may be empty. + * + * The host or ip is either an IPv4 address (as parsed by inet_pton()), an + * IPv6 address in '[' and ']' and parseable by inet_aton() or a hostname + * terminated by the last colon or by the NUL character. + * + * The port number may be specified numerically or symbolically and starts + * with the last colon. + * + * The functions sets the chost, cport, trans, read_community and + * write_community fields on success and the error field on errors. + * The chost and cport fields are allocated by malloc(3), their previous + * content is deallocated by free(3). + * + * The function explicitly allows mismatches between the transport and + * the address type in order to support IPv4 in IPv6 addresses. + * + * \param sc client struct to fill + * \param str string to parse + * + * \return 0 on success and -1 on errors + */ +int +snmp_parse_server(struct snmp_client *sc, const char *str) +{ + const char *const orig = str; + + /* parse input */ + int def_trans = 0, trans = get_transp(sc, &str); + if (trans < 0) + return (-1); + /* choose automatically */ + if (orig == str) + def_trans = 1; + + const char *const comm[2] = { + str, + get_comm(sc, &str), + }; + if (comm[1] == NULL) + return (-1); + + const char *const ipv6[2] = { + str + 1, + get_ipv6(sc, &str), + }; + if (ipv6[1] == NULL) + return (-1); + + const char *ipv4[2] = { + str, + str, + }; + + const char *host[2] = { + str, + str, + }; + + if (ipv6[0] == ipv6[1]) { + ipv4[1] = get_ipv4(sc, &str); + + if (ipv4[0] == ipv4[1]) + host[1] = get_host(sc, &str); + } + + const char *port[2] = { + str + 1, + get_port(sc, &str), + }; + if (port[1] == NULL) + return (-1); + + if (*str != '\0') { + seterr(sc, "junk at end of server specification '%s'", str); + return (-1); + } + +#if DEBUG_PARSE + printf("transp: %d (def=%d)\n", trans, def_trans); + printf("comm: %zu %zu\n", comm[0] - orig, comm[1] - orig); + printf("ipv6: %zu %zu\n", ipv6[0] - orig, ipv6[1] - orig); + printf("ipv4: %zu %zu\n", ipv4[0] - orig, ipv4[1] - orig); + printf("host: %zu %zu\n", host[0] - orig, host[1] - orig); + printf("port: %zu %zu\n", port[0] - orig, port[1] - orig); +#endif + + /* analyse and allocate */ + char *chost; + + if (ipv6[0] != ipv6[1]) { + if ((chost = save_str(sc, ipv6)) == NULL) return (-1); + if (def_trans || trans == SNMP_TRANS_UDP) + /* assume the user meant udp6:: */ + trans = SNMP_TRANS_UDP6; + } else if (ipv4[0] != ipv4[1]) { + if ((chost = save_str(sc, ipv4)) == NULL) + return (-1); + if (def_trans) + trans = SNMP_TRANS_UDP; + } else { + if ((chost = save_str(sc, host)) == NULL) + return (-1); + + if (def_trans) { + /* + * Default transport is UDP unless the host contains + * a slash in which case we default to DGRAM. + */ + for (const char *p = host[0]; p < host[1]; p++) + if (*p == '/') { + trans = SNMP_TRANS_LOC_DGRAM; + break; + } } } + + char *cport; + + if (port[0] == port[1] && ( + trans == SNMP_TRANS_UDP || trans == SNMP_TRANS_UDP6)) { + /* If port was not specified, use "snmp" name by default */ + cport = strdup("snmp"); + } else + cport = save_str(sc, port); + + if (cport == NULL) { + free(chost); + return (-1); + } + + /* commit */ + sc->trans = trans; + + /* + * If community string was specified and it is empty, overwrite it. + * If it was not specified, use default. + */ + if (comm[0] != comm[1] || strrchr(comm[0], '@') != NULL) { + strncpy(sc->read_community, comm[0], comm[1] - comm[0]); + sc->read_community[comm[1] - comm[0]] = '\0'; + strncpy(sc->write_community, comm[0], comm[1] - comm[0]); + sc->write_community[comm[1] - comm[0]] = '\0'; + } + + free(sc->chost); + sc->chost = chost; + free(sc->cport); + sc->cport = cport; + +#if DEBUG_PARSE + printf("Committed values:\n"); + printf("trans: %d\n", sc->trans); + printf("comm: '%s'/'%s'\n", sc->read_community, sc->write_community); + printf("host: '%s'\n", sc->chost); + printf("port: '%s'\n", sc->cport); +#endif return (0); } Index: vendor/bsnmp/dist/lib/snmpclient.h =================================================================== --- vendor/bsnmp/dist/lib/snmpclient.h (revision 359489) +++ vendor/bsnmp/dist/lib/snmpclient.h (revision 359490) @@ -1,201 +1,202 @@ /* * 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 +#define SNMP_TRANS_UDP6 3 /* 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 */ Index: vendor/bsnmp/dist/lib/snmpcrypto.c =================================================================== --- vendor/bsnmp/dist/lib/snmpcrypto.c (revision 359489) +++ vendor/bsnmp/dist/lib/snmpcrypto.c (revision 359490) @@ -1,402 +1,435 @@ /*- * 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 $ + * $FreeBSD: head/contrib/bsnmp/lib/snmpcrypto.c 339270 2018-10-09 21:28:26Z gjb $ */ #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 +#ifdef HAVE_LIBCRYPTO + 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; + EVP_MD_CTX *ctx; - err = snmp_digest_init(&pdu->user, &ctx, &dtype, &keylen); + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + return (SNMP_CODE_FAILED); + err = snmp_digest_init(&pdu->user, ctx, &dtype, &keylen); + if (err <= 0) + EVP_MD_CTX_free(ctx); 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) + 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) + 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); + EVP_MD_CTX_free(ctx); return (SNMP_CODE_BADDIGEST); } memcpy(digest, md, SNMP_USM_AUTH_SIZE); - EVP_MD_CTX_cleanup(&ctx); + EVP_MD_CTX_free(ctx); return (SNMP_CODE_OK); failed: - EVP_MD_CTX_cleanup(&ctx); + EVP_MD_CTX_free(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; + 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) + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) return (SNMP_CODE_FAILED); + if (EVP_EncryptInit(ctx, ctype, pdu->user.priv_key, iv) != 1) + goto failed; - if (EVP_EncryptUpdate(&ctx, pdu->scoped_ptr, &olen, pdu->scoped_ptr, + 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_EncryptFinal(ctx, pdu->scoped_ptr + olen, &olen) != 1) + goto failed; - EVP_CIPHER_CTX_cleanup(&ctx); + EVP_CIPHER_CTX_free(ctx); return (SNMP_CODE_OK); + +failed: + EVP_CIPHER_CTX_free(ctx); + return (SNMP_CODE_FAILED); } 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; + 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); + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) + return (SNMP_CODE_FAILED); + if (EVP_DecryptInit(ctx, ctype, pdu->user.priv_key, iv) != 1 || + EVP_CIPHER_CTX_set_padding(ctx, 0) != 1) + goto failed; - if (EVP_DecryptUpdate(&ctx, pdu->scoped_ptr, &olen, pdu->scoped_ptr, + 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_DecryptFinal(ctx, pdu->scoped_ptr + olen, &olen) != 1) + goto failed; - EVP_CIPHER_CTX_cleanup(&ctx); + EVP_CIPHER_CTX_free(ctx); return (SNMP_CODE_OK); + +failed: + EVP_CIPHER_CTX_free(ctx); + return (SNMP_CODE_EDECRYPT); } /* [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; + 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); + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + return (SNMP_CODE_FAILED); + + err = snmp_digest_init(user, ctx, &dtype, &keylen); + if (err <= 0) + EVP_MD_CTX_free(ctx); 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) + if (EVP_DigestUpdate(ctx, authbuf, SNMP_EXTENDED_KEY_SIZ) != 1) goto failed; } - if (EVP_DigestFinal(&ctx, user->auth_key, &olen) != 1) + if (EVP_DigestFinal(ctx, user->auth_key, &olen) != 1) goto failed; - EVP_MD_CTX_cleanup(&ctx); + EVP_MD_CTX_free(ctx); return (SNMP_CODE_OK); failed: - EVP_MD_CTX_cleanup(&ctx); + EVP_MD_CTX_free(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; + 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); + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + 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); + err = snmp_digest_init(user, ctx, &dtype, &keylen); + if (err <= 0) + EVP_MD_CTX_free(ctx); 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); + if (EVP_DigestUpdate(ctx, authbuf, 2 * keylen + elen) != 1 || + EVP_DigestFinal(ctx, user->auth_key, &olen) != 1) { + EVP_MD_CTX_free(ctx); return (SNMP_CODE_BADDIGEST); } - EVP_MD_CTX_cleanup(&ctx); + EVP_MD_CTX_free(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; + EVP_MD_CTX *ctx; - err = snmp_digest_init(user, &ctx, &dtype, &keylen); + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + return (SNMP_CODE_FAILED); + + err = snmp_digest_init(user, ctx, &dtype, &keylen); + if (err <= 0) + EVP_MD_CTX_free(ctx); 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); + if (EVP_DigestUpdate(ctx, keychange, 2 * keylen) != 1 || + EVP_DigestFinal(ctx, keychange, &olen) != 1) { + EVP_MD_CTX_free(ctx); return (SNMP_CODE_BADDIGEST); } - EVP_MD_CTX_cleanup(&ctx); + EVP_MD_CTX_free(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 */ Index: vendor/bsnmp/dist/lib/tc.def =================================================================== --- vendor/bsnmp/dist/lib/tc.def (revision 359489) +++ vendor/bsnmp/dist/lib/tc.def (revision 359490) @@ -1,48 +1,56 @@ #- # 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 ) +typedef InetAddressType ENUM ( + 0 unknown + 1 ipv4 + 2 ipv6 + 3 ipv4z + 4 ipv6z + 16 dns +) Index: vendor/bsnmp/dist/snmp_mibII/Makefile.in =================================================================== --- vendor/bsnmp/dist/snmp_mibII/Makefile.in (revision 359489) +++ vendor/bsnmp/dist/snmp_mibII/Makefile.in (nonexistent) @@ -1,48 +0,0 @@ -# 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/dist/snmp_mibII/Makefile.in ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: vendor/bsnmp/dist/snmp_mibII/mibII.c =================================================================== --- vendor/bsnmp/dist/snmp_mibII/mibII.c (revision 359489) +++ vendor/bsnmp/dist/snmp_mibII/mibII.c (revision 359490) @@ -1,1814 +1,1870 @@ /* * 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, + if ((hc_update_timer = timer_start_repeat(ticks, ticks, 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) { + static int kmib[2] = { -1, 0 }; /* for sysctl net.ifdescr_maxlen */ + int name[6]; + size_t kmiblen = nitems(kmib); size_t len; void *newmib; struct ifmibdata oldmib = ifp->mib; struct ifreq irr; + u_int alias_maxlen = MIBIF_ALIAS_SIZE_MAX; 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: + /* + * Find sysctl mib for net.ifdescr_maxlen (one time). + * kmib[0] == -1 at first call to mib_fetch_ifmib(). + * Then kmib[0] > 0 if we found sysctl mib for net.ifdescr_maxlen. + * Else, kmib[0] == 0 (unexpected error from a kernel). + */ + if (kmib[0] < 0 && + sysctlnametomib("net.ifdescr_maxlen", kmib, &kmiblen) < 0) { + kmib[0] = 0; + syslog(LOG_WARNING, "sysctlnametomib net.ifdescr_maxlen: %m"); + } + + /* + * Fetch net.ifdescr_maxlen value every time to catch up with changes. + */ + len = sizeof(alias_maxlen); + if (kmib[0] > 0 && sysctl(kmib, 2, &alias_maxlen, &len, NULL, 0) < 0) { + /* unexpected error from the kernel, use default value */ + alias_maxlen = MIBIF_ALIAS_SIZE_MAX; + syslog(LOG_WARNING, "sysctl net.ifdescr_maxlen: %m"); + } + + /* + * Kernel limit might be decreased after interfaces got + * their descriptions assigned. Try to obtain them anyway. + */ + if (alias_maxlen == 0) + alias_maxlen = MIBIF_ALIAS_SIZE_MAX; + + /* + * Allocate maximum memory for a buffer and later reallocate + * to free extra memory. + */ + if ((ifp->alias = malloc(alias_maxlen)) == NULL) { + syslog(LOG_WARNING, "malloc(%d) failed: %m", (int)alias_maxlen); + goto fin; + } + 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); + irr.ifr_buffer.buffer = ifp->alias; + irr.ifr_buffer.length = alias_maxlen; if (ioctl(mib_netsock, SIOCGIFDESCR, &irr) == -1) { - MIBIF_PRIV(ifp)->alias[0] = 0; + free(ifp->alias); + ifp->alias = NULL; if (errno != ENOMSG) syslog(LOG_WARNING, "SIOCGIFDESCR (%s): %m", ifp->name); } else if (irr.ifr_buffer.buffer == NULL) { - MIBIF_PRIV(ifp)->alias[0] = 0; + free(ifp->alias); + ifp->alias = NULL; syslog(LOG_WARNING, "SIOCGIFDESCR (%s): too long (%zu)", ifp->name, irr.ifr_buffer.length); + } else { + ifp->alias_size = strnlen(ifp->alias, alias_maxlen) + 1; + + if (ifp->alias_size > MIBIF_ALIAS_SIZE) + ifp->alias_size = MIBIF_ALIAS_SIZE; + + if (ifp->alias_size < alias_maxlen) + ifp->alias = realloc(ifp->alias, ifp->alias_size); } + + fin: 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(); } + if (ifp->alias != NULL) { + free(ifp->alias); + ifp->alias = NULL; + } 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" +extern const struct snmp_module config; 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; } Index: vendor/bsnmp/dist/snmp_mibII/mibII.h =================================================================== --- vendor/bsnmp/dist/snmp_mibII/mibII.h (revision 359489) +++ vendor/bsnmp/dist/snmp_mibII/mibII.h (revision 359490) @@ -1,278 +1,276 @@ /* * 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 */ +/* maximum size of interface alias unless overridden with net.ifdescr_maxlen */ #define MIBIF_ALIAS_SIZE (64 + 1) +#define MIBIF_ALIAS_SIZE_MAX 1024 /* * 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); Index: vendor/bsnmp/dist/snmp_mibII/mibII_interfaces.c =================================================================== --- vendor/bsnmp/dist/snmp_mibII/mibII_interfaces.c (revision 359489) +++ vendor/bsnmp/dist/snmp_mibII/mibII_interfaces.c (revision 359490) @@ -1,542 +1,521 @@ /* * 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); + ret = string_get(value, ifp->alias, ifp->alias_size - 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); } Index: vendor/bsnmp/dist/snmp_mibII/snmp_mibII.h =================================================================== --- vendor/bsnmp/dist/snmp_mibII/snmp_mibII.h (revision 359489) +++ vendor/bsnmp/dist/snmp_mibII/snmp_mibII.h (revision 359490) @@ -1,169 +1,172 @@ /* * 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; + char *alias; + size_t alias_size; + /* 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 Index: vendor/bsnmp/dist/snmp_ntp/Makefile.in =================================================================== --- vendor/bsnmp/dist/snmp_ntp/Makefile.in (revision 359489) +++ vendor/bsnmp/dist/snmp_ntp/Makefile.in (nonexistent) @@ -1,38 +0,0 @@ -# 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/dist/snmp_ntp/Makefile.in ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: vendor/bsnmp/dist/snmp_ntp/snmp_ntp.c =================================================================== --- vendor/bsnmp/dist/snmp_ntp/snmp_ntp.c (revision 359489) +++ vendor/bsnmp/dist/snmp_ntp/snmp_ntp.c (revision 359490) @@ -1,1598 +1,1600 @@ /* - * Copyright (c) 2005 + * Copyright (c) 2005,2018 * 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" + +#define SNMPTREE_TYPES #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(); } Index: vendor/bsnmp/dist/snmp_target/Makefile.in =================================================================== --- vendor/bsnmp/dist/snmp_target/Makefile.in (revision 359489) +++ vendor/bsnmp/dist/snmp_target/Makefile.in (nonexistent) @@ -1,38 +0,0 @@ -# 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/dist/snmp_target/Makefile.in ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: vendor/bsnmp/dist/snmp_target/target_snmp.c =================================================================== --- vendor/bsnmp/dist/snmp_target/target_snmp.c (revision 359489) +++ vendor/bsnmp/dist/snmp_target/target_snmp.c (revision 359490) @@ -1,842 +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[] = \ +static const char target_comment[] = \ "This module implements SNMP Management Target MIB Module defined in RFC 3413."; +extern const struct snmp_module config; 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, }; Index: vendor/bsnmp/dist/snmp_usm/Makefile.in =================================================================== --- vendor/bsnmp/dist/snmp_usm/Makefile.in (revision 359489) +++ vendor/bsnmp/dist/snmp_usm/Makefile.in (nonexistent) @@ -1,40 +0,0 @@ -# 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/dist/snmp_usm/Makefile.in ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: vendor/bsnmp/dist/snmp_usm/usm_snmp.c =================================================================== --- vendor/bsnmp/dist/snmp_usm/usm_snmp.c (revision 359489) +++ vendor/bsnmp/dist/snmp_usm/usm_snmp.c (revision 359490) @@ -1,620 +1,620 @@ /*- - * Copyright (c) 2010 The FreeBSD Foundation + * 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_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 +#define SNMPTREE_TYPES #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[] = \ +static const char usm_comment[] = "This module implements SNMP User-based Security Model defined in RFC 3414."; +extern const struct snmp_module config; 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, }; Index: vendor/bsnmp/dist/snmp_vacm/Makefile.in =================================================================== --- vendor/bsnmp/dist/snmp_vacm/Makefile.in (revision 359489) +++ vendor/bsnmp/dist/snmp_vacm/Makefile.in (nonexistent) @@ -1,38 +0,0 @@ -# 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/dist/snmp_vacm/Makefile.in ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: vendor/bsnmp/dist/snmp_vacm/vacm_snmp.c =================================================================== --- vendor/bsnmp/dist/snmp_vacm/vacm_snmp.c (revision 359489) +++ vendor/bsnmp/dist/snmp_vacm/vacm_snmp.c (revision 359490) @@ -1,1028 +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[] = \ +static const char vacm_comment[] = "This module implements SNMP View-based Access Control Model defined in RFC 3415."; +extern const struct snmp_module config; 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, }; Index: vendor/bsnmp/dist/snmpd/Makefile.in =================================================================== --- vendor/bsnmp/dist/snmpd/Makefile.in (revision 359489) +++ vendor/bsnmp/dist/snmpd/Makefile.in (nonexistent) @@ -1,45 +0,0 @@ -# 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/dist/snmpd/Makefile.in ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: vendor/bsnmp/dist/snmpd/BEGEMOT-SNMPD.txt =================================================================== --- vendor/bsnmp/dist/snmpd/BEGEMOT-SNMPD.txt (revision 359489) +++ vendor/bsnmp/dist/snmpd/BEGEMOT-SNMPD.txt (revision 359490) @@ -1,579 +1,691 @@ -- -- Copyright (c) 2001-2003 -- Fraunhofer Institute for Open Communication Systems (FhG Fokus). -- All rights reserved. -- +-- Copyright (c) 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: 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 + Integer32, Unsigned32, IpAddress FROM SNMPv2-SMI TEXTUAL-CONVENTION, TruthValue, RowStatus FROM SNMPv2-TC - MODULE-COMPLIANCE, OBJECT-GROUP - FROM SNMPv2-CONF + InetAddressType, InetAddress, InetPortNumber + FROM INET-ADDRESS-MIB begemot FROM BEGEMOT-MIB; begemotSnmpd MODULE-IDENTITY - LAST-UPDATED "201801190000Z" + LAST-UPDATED "201808080000Z" 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." + REVISION "201808080000Z" + DESCRIPTION + "Add the begemotSnmpdTransInetTable." ::= { 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) + SYNTAX Integer32 (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) + SYNTAX Integer32 (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) + SYNTAX Integer32 (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 + STATUS deprecated 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 + STATUS deprecated 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 + STATUS deprecated DESCRIPTION "The IP address to bind to." ::= { begemotSnmpdPortEntry 1 } begemotSnmpdPortPort OBJECT-TYPE - SYNTAX INTEGER (1..65535) + SYNTAX Integer32 (1..65535) MAX-ACCESS not-accessible - STATUS current + STATUS deprecated 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 + STATUS deprecated 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 + begemotSnmpdCommunityPermission Unsigned32 } 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) + SYNTAX Unsigned32 (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) + SYNTAX Integer32 (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 } +-- ---------------------------------------------------------------------- -- +-- Internet port table. +-- +BegemotSnmpdTransportProto ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "A value that represents the type of protocol to be used for + listening on a socket. The following protocols are currently + used: + + udp(1) Use UDP for IPv4 and IPv6 sockets." + SYNTAX INTEGER { + udp(1) + } + +begemotSnmpdTransInetTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotSnmpdTransInetEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "This table contains all the ports the daemon should listen on. + Entries can be created at initialization time via the config + file or at run time via a SET. One row can map to several open + sockets in the case of InetAddressType::dns rows. These rows + open one socket for each address returned by getaddrinfo(3). + for SNMP messages." + ::= { begemotSnmpdObjects 11 } + +begemotSnmpdTransInetEntry OBJECT-TYPE + SYNTAX BegemotSnmpdTransInetEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A row of the internet port table. Each row may map to one or + more listening sockets." + INDEX { + begemotSnmpdTransInetAddressType, + begemotSnmpdTransInetAddress, + begemotSnmpdTransInetPort, + begemotSnmpdTransInetProto + } + ::= { begemotSnmpdTransInetTable 1 } + +BegemotSnmpdTransInetEntry ::= SEQUENCE { + begemotSnmpdTransInetAddressType InetAddressType, + begemotSnmpdTransInetAddress InetAddress, + begemotSnmpdTransInetPort InetPortNumber, + begemotSnmpdTransInetProto BegemotSnmpdTransportProto, + begemotSnmpdTransInetStatus RowStatus +} + +begemotSnmpdTransInetAddressType OBJECT-TYPE + SYNTAX InetAddressType + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The type of the address. Only ipv4, ipv6, ipv6z and dns are + supported." + ::= { begemotSnmpdTransInetEntry 1 } + +begemotSnmpdTransInetAddress OBJECT-TYPE + SYNTAX InetAddress (SIZE (0..64)) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The address. For ipv4 addresses the length must be 4, ipv6 + addresses have a length of 16 and ipv6z addresses a length of + 20 where the last four bytes are the interface index in big + endian format. dns addresses may be of zero-length in which case + getaddrinfo() generates INADDR_ANY and its IPv6 equivalent. dns + addresses will open a socket for all addresses returned by + getaddrinfo()." + ::= { begemotSnmpdTransInetEntry 2 } + +begemotSnmpdTransInetPort OBJECT-TYPE + SYNTAX InetPortNumber (1..65535) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The port to listen on for SNMP messages." + ::= { begemotSnmpdTransInetEntry 3 } + +begemotSnmpdTransInetProto OBJECT-TYPE + SYNTAX BegemotSnmpdTransportProto + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The protocol to use. Currently only the value udp(1) is supported." + ::= { begemotSnmpdTransInetEntry 4 } + +begemotSnmpdTransInetStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of the conceptual row. A row may be created using + createAndGo(4) or createAndWait(5). An inactive row can be + activated writing active(1) and an active row can be inactivated + by writing notInService(2). Finally active or inactive rows can be + deleted by writing the value destroy(6). The value of this field + will never read as notReady(3)." + ::= { begemotSnmpdTransInetEntry 5 } + +-- -- XXX These should go into their own MIB -- begemotSnmpdTransUdp OBJECT IDENTIFIER ::= { begemotSnmpdTransportMappings 2 } begemotSnmpdTransLsock OBJECT IDENTIFIER ::= { begemotSnmpdTransportMappings 3 } +begemotSnmpdTransInet OBJECT IDENTIFIER ::= { begemotSnmpdTransportMappings 4 } END Index: vendor/bsnmp/dist/snmpd/main.c =================================================================== --- vendor/bsnmp/dist/snmpd/main.c (revision 359489) +++ vendor/bsnmp/dist/snmpd/main.c (revision 359490) @@ -1,3111 +1,3142 @@ /* * 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" +#include "trans_inet.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; + port->transport = t; 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]; + char client[INET6_ADDRSTRLEN]; #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 (tport->transport->vtab->send != NULL) + slen = tport->transport->vtab->send(tport, sndbuf, + sndlen, pi->peer, pi->peerlen); + else + slen = tport->transport->vtab->send2(tport, sndbuf, + sndlen, pi); 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 + * Send a PDU to a given port. If this is a multi-socket port, use the + * first socket. */ 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 (trans->vtab->send != NULL) + len = trans->vtab->send(tp, sndbuf, sndlen, addr, addrlen); + else + len = trans->vtab->send2(tp, sndbuf, sndlen, NULL); 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 + * + * \param pi input instance */ void snmpd_input_close(struct port_input *pi) { - if (pi->id != NULL) + if (pi->id != NULL) { fd_deselect(pi->id); - if (pi->fd >= 0) + pi->id = NULL; + } + if (pi->fd >= 0) { (void)close(pi->fd); - if (pi->buf != NULL) + pi->fd = -1; + } + if (pi->buf != NULL) { free(pi->buf); + pi->buf = NULL; + } } /* + * Initialize an input source. + * + * \param pi input instance + */ +void +snmpd_input_init(struct port_input *pi) +{ + pi->id = NULL; + pi->fd = -1; + pi->buf = NULL; +} + +/* * 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 = arc4random(); - 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"); + if (inet_trans.start() != SNMP_ERR_NOERROR) + syslog(LOG_WARNING, "cannot start INET 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); } } Index: vendor/bsnmp/dist/snmpd/snmpd.config =================================================================== --- vendor/bsnmp/dist/snmpd/snmpd.config (revision 359489) +++ vendor/bsnmp/dist/snmpd/snmpd.config (revision 359490) @@ -1,104 +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/snmpd/snmpd.config,v 1.16 2006/02/14 09:04:20 brandt_h Exp $ # -# Example configuration file. +# Example configuration file for testing. # # # Set some common variables # host := foo.bar.com location := "Room 200" contact := "sysmeister@bar.com" system := 1 # FreeBSD -traphost := noc.bar.com +traphost := localhost trapport := 162 read := "public" -# Uncomment the line below that sets the community string -# to enable write access. -write := "geheim" +write := "geheim" # take care - this allows writing trap := "mytrap" +securityModelSNMPv1 := 1 +securityModelSNMPv2c := 2 + +noAuthNoPriv := 1 + # # Configuration # %snmpd begemotSnmpdDebugDumpPdus = 2 begemotSnmpdDebugSyslogPri = 7 +begemotSnmpdDebugSnmpTrace = 0 # -# Set the read and write communities. +# Set community strings. # -# 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. +# Each community string has a permission attached to it - 1 for read only +# and 2 for read/write. Default is 1. Community strings must be unique. # # 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" +begemotSnmpdCommunityPermission.0.1 = 1 +#begemotSnmpdCommunityString.0.2 = $(write) +#begemotSnmpdCommunityPermission.0.2 = 2 +#begemotSnmpdCommunityString.0.3 = "otherPublic" begemotSnmpdCommunityDisable = 1 # open standard SNMP ports -begemotSnmpdPortStatus.[$(host)].161 = 1 -begemotSnmpdPortStatus.127.0.0.1.161 = 1 +# 0.0.0.0:161 +begemotSnmpdTransInetStatus.1.4.0.0.0.0.161.1 = 4 +# test the port table; IPv4 address +# 127.0.0.1:10161 +begemotSnmpdTransInetStatus.1.4.127.0.0.1.10161.1 = 4 + +# test the port table; IPv6 address +# ::1:10162 +begemotSnmpdTransInetStatus.2.16.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.10162.1 = 4 +# :::10163 +begemotSnmpdTransInetStatus.2.16.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.10163.1 = 4 +# fe80::1%1:10164 - requires inet fe80::1%em0/64 +begemotSnmpdTransInetStatus.4.20.254.128.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.1.10164.1 = 4 +# fe80::1%2:10164 - requires inet fe80::1%em1/64 +begemotSnmpdTransInetStatus.4.20.254.128.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.2.10164.1 = 4 +# fe80::1:10170 - should fail (no scope index) +# begemotSnmpdTransInetStatus.2.16.254.128.0.0.0.0.0.0.0.0.0.0.0.0.0.1.10170.1 = 4 +# fe80::1%0:10170 - should fail (default scope index for link local address) +# begemotSnmpdTransInetStatus.4.20.254.128.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.10170.1 = 4 + +# test the port table; DNS address +# :10165 UDPv4 and UDPv6 +begemotSnmpdTransInetStatus.16.0.10165.1 = 4 +# 127.0.0.1:10166 +# ::1:10166 +begemotSnmpdTransInetStatus.16."localhost".10166.1 = 4 +# ::1:10167 +begemotSnmpdTransInetStatus.16."localhost6".10167.1 = 4 +# fe80::1%em0:10168 - requires inet fe80::$em0/64 +begemotSnmpdTransInetStatus.16."fe80::1%em0".10168.1 = 4 +# fe80::1%em1:10169 - requires inet fe80::$em1/64 +begemotSnmpdTransInetStatus.16."fe80::1%em1".10169.1 = 4 + # open a unix domain socket -begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1 -begemotSnmpdLocalPortType."/var/run/snmpd.sock" = 4 +# 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" = "../snmp_mibII/.libs/snmp_mibII.so" begemotSnmpdModulePath."mibII" = "/usr/local/lib/snmp_mibII.so" # +# SNMPv3 notification targets +# +#begemotSnmpdModulePath."target" = "../snmp_target/.libs/snmp_target.so" +begemotSnmpdModulePath."target" = "/usr/local/lib/snmp_target.so" + +# +# SNMPv3 user-based security module +# +#begemotSnmpdModulePath."usm" = "../snmp_usm/.libs/snmp_usm.so" +begemotSnmpdModulePath."usm" = "/usr/local/lib/snmp_usm.so" + +# +# SNMPv3 view-based access control module +# +#begemotSnmpdModulePath."vacm" = "../snmp_vacm/.libs/snmp_vacm.so" +begemotSnmpdModulePath."vacm" = "/usr/local/lib/snmp_vacm.so" + +# # Netgraph module # -begemotSnmpdModulePath."netgraph" = "/usr/local/lib/snmp_netgraph.so" +# begemotSnmpdModulePath."netgraph" = "/usr/local/lib/snmp_netgraph.so" +# %netgraph +# begemotNgControlNodeName = "snmpd" -%netgraph -begemotNgControlNodeName = "snmpd" +%vacm + +internetoid := 1.3.6.1 +internetoidlen := 4 + +vacmSecurityToGroupStatus.$(securityModelSNMPv1).$(read) = 4 +vacmGroupName.$(securityModelSNMPv1).$(read) = $(read) + +vacmSecurityToGroupStatus.$(securityModelSNMPv2c).$(read) = 4 +vacmGroupName.$(securityModelSNMPv2c).$(read) = $(read) + +vacmSecurityToGroupStatus.$(securityModelSNMPv2c).$(write) = 4 +vacmGroupName.$(securityModelSNMPv2c).$(write) = $(write) + +vacmViewTreeFamilyStatus."internet".$(internetoidlen).$(internetoid) = 4 + +vacmAccessStatus.$(read)."".$(securityModelSNMPv1).$(noAuthNoPriv) = 4 +vacmAccessReadViewName.$(read)."".$(securityModelSNMPv1).$(noAuthNoPriv) = "internet" + +vacmAccessStatus.$(write)."".$(securityModelSNMPv2c).$(noAuthNoPriv) = 4 +vacmAccessStatus.$(read)."".$(securityModelSNMPv2c).$(noAuthNoPriv) = 4 +vacmAccessReadViewName.$(write)."".$(securityModelSNMPv2c).$(noAuthNoPriv) = "internet" +vacmAccessReadViewName.$(read)."".$(securityModelSNMPv2c).$(noAuthNoPriv) = "internet" +vacmAccessWriteViewName.$(write)."".$(securityModelSNMPv2c).$(noAuthNoPriv) = "internet" +vacmAccessWriteViewName.$(read)."".$(securityModelSNMPv2c).$(noAuthNoPriv) = "internet" + Index: vendor/bsnmp/dist/snmpd/snmpd.h =================================================================== --- vendor/bsnmp/dist/snmpd/snmpd.h (revision 359489) +++ vendor/bsnmp/dist/snmpd/snmpd.h (revision 359490) @@ -1,342 +1,346 @@ /* * 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 *); +void snmpd_input_init(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 *); + + /** send via a multi-socket port */ + ssize_t (*send2)(struct tport *, const u_char *, size_t, + 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 Index: vendor/bsnmp/dist/snmpd/snmpmod.h =================================================================== --- vendor/bsnmp/dist/snmpd/snmpmod.h (revision 359489) +++ vendor/bsnmp/dist/snmpd/snmpmod.h (revision 359490) @@ -1,627 +1,669 @@ /* * 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. */ + +/* + * First set of macros is used when the link is embedded into sub-struct + * and links these sub-structs. The sub-struct must be the first field. + * + * The list is a list of the subfield types. + */ +#define INSERT_OBJECT_OID_LINK_INDEX_TYPE(PTR, LIST, LINK, INDEX, SUBF) do {\ + typedef __typeof ((PTR)->SUBF) _subf_type; \ + _subf_type *_lelem; \ + \ + TAILQ_FOREACH(_lelem, (LIST), LINK) \ + if (asn_compare_oid(&_lelem->INDEX, &(PTR)->SUBF.INDEX) > 0)\ + break; \ + if (_lelem == NULL) \ + TAILQ_INSERT_TAIL((LIST), &(PTR)->SUBF, LINK); \ + else \ + TAILQ_INSERT_BEFORE(_lelem, &(PTR)->SUBF, LINK); \ + } while (0) + +#define NEXT_OBJECT_OID_LINK_INDEX_TYPE(LIST, OID, SUB, LINK, INDEX, TYPE) ({\ + __typeof (TAILQ_FIRST((LIST))) _lelem; \ + \ + TAILQ_FOREACH(_lelem, (LIST), LINK) \ + if (index_compare(OID, SUB, &_lelem->INDEX) < 0) \ + break; \ + (TYPE *)(_lelem); \ + }) + +#define FIND_OBJECT_OID_LINK_INDEX_TYPE(LIST, OID, SUB, LINK, INDEX, TYPE) ({\ + __typeof (TAILQ_FIRST((LIST))) _lelem; \ + \ + TAILQ_FOREACH(_lelem, (LIST), LINK) \ + if (index_compare(OID, SUB, &_lelem->INDEX) == 0) \ + break; \ + (TYPE *)(_lelem); \ + }) + +/* + * This set of macros allows specification of the link and index name. + * The index is an OID. + */ #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 Index: vendor/bsnmp/dist/snmpd/trans_inet.c =================================================================== --- vendor/bsnmp/dist/snmpd/trans_inet.c (nonexistent) +++ vendor/bsnmp/dist/snmpd/trans_inet.c (revision 359490) @@ -0,0 +1,1341 @@ +/* + * Copyright (c) 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: bsnmp/snmpd/trans_udp.c,v 1.5 2005/10/04 08:46:56 brandt_h Exp $ + * + * Internet transport + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "asn1.h" +#include "snmp.h" +#include "snmpmod.h" + +#include "snmpd.h" + +#define SNMPTREE_TYPES +#define SNMPENUM_FUNCS +#include "tree.h" +#include "oid.h" + +extern const struct transport_def inet_trans; + +struct inet_port; +struct inet_port_params; +struct port_sock; + +typedef int create_func(struct inet_port *, struct inet_port_params *); +typedef void input_func(int, void *); +typedef int activate_func(struct inet_port *); +typedef void deactivate_func(struct inet_port *); +typedef void parse_ctrl_func(struct port_sock *, const struct msghdr *); +typedef void setsrc_func(struct port_sock *, struct msghdr *); + +static create_func ipv4_create; +static input_func ipv4_input; +static activate_func ipv4_activate; +static deactivate_func ipv4_deactivate; +static parse_ctrl_func ipv4_parse_ctrl; +static setsrc_func ipv4_setsrc; + +static create_func ipv6_create; +static input_func ipv6_input; +static activate_func ipv6_activate; +static deactivate_func ipv6_deactivate; +static parse_ctrl_func ipv6_parse_ctrl; +static setsrc_func ipv6_setsrc; + +static create_func ipv6z_create; + +static create_func dns_create; +static activate_func dns_activate; +static deactivate_func dns_deactivate; + +struct port_sock { + /* common input stuff; must be first */ + struct port_input input; + + /** link field */ + TAILQ_ENTRY(port_sock) link; + + /** pointer to parent */ + struct inet_port *port; + + /** bind address */ + struct sockaddr_storage bind_addr; + + /** reply destination */ + struct sockaddr_storage ret_dest; + + /** need to set source address in reply; set for INADDR_ANY */ + bool set_ret_source; + + /** address of the receive interface */ + union { + /** IPv4 case */ + struct in_addr a4; + + /** IPv6 case */ + struct in6_pktinfo a6; + } ret_source; + + /** parse control message */ + parse_ctrl_func *parse_ctrl; + + /** set source address for a send() */ + setsrc_func *setsrc; +}; +static_assert(offsetof(struct port_sock, input) == 0, + "input not first in port_sock"); + +/** + * Table row for the inet ports. + * + * When actived each row can have one or several open sockets. For ipv6, + * ipv4 and ipv6z addresses it is always one, for dns addresses more than + * one socket can be open. + */ +struct inet_port { + /** common i/o port stuff (must be first) */ + struct tport tport; + + /** transport protocol */ + enum BegemotSnmpdTransportProto proto; + + /** row status */ + enum RowStatus row_status; + + /** socket list */ + TAILQ_HEAD(, port_sock) socks; + + /** value for InetAddressType::dns */ + char *dns_addr; + + /** port number in dns case; network byte order */ + uint16_t dns_port; + + /** create a port */ + create_func *create; + + /** activate a port */ + activate_func *activate; + + /** deactivate port */ + deactivate_func *deactivate; +}; +static_assert(offsetof(struct inet_port, tport) == 0, + "tport not first in inet_port"); + +/** to be used in bind_addr field */ +#define AF_DNS AF_VENDOR00 + +/** registered transport */ +static struct transport *my_trans; + +/** set operation */ +enum { + SET_CREATED, + SET_ACTIVATED, + SET_DEACTIVATE, + SET_DESTROY, +}; + +/** length of the control data buffer */ +static const size_t RECV_CBUF_SIZE = + MAX(CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) + + CMSG_SPACE(sizeof(struct in_addr)), + CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) + + CMSG_SPACE(sizeof(struct in6_pktinfo))); + +/** length of the control data buffer */ +static const size_t XMIT_CBUF_SIZE = + MAX(CMSG_SPACE(sizeof(struct in_addr)), + CMSG_SPACE(sizeof(struct in6_pktinfo))); + +/** + * Start the transport. This registers the transport with the + * transport table. + * + * \return SNMP error code + */ +static int +inet_start(void) +{ + return (trans_register(&inet_trans, &my_trans)); +} + +/** + * Stop the transport. This tries to unregister the transport which + * in turn fails if the list of ports is not empty. + * + * \return SNMP error code + */ +static int +inet_stop(int force __unused) +{ + if (my_trans != NULL) + if (trans_unregister(my_trans) != 0) + return (SNMP_ERR_GENERR); + return (SNMP_ERR_NOERROR); +} + +/** + * Deactivate SNMP port. + * + * \param tp port to close + */ +static void +deactivate_port(struct inet_port *p) +{ + p->deactivate(p); +} + +/* + * This function activates a port. For ports opened via the config files + * this is called just before entering the event loop. For ports create + * during runtime this is called when the RowStatus is set to Active or + * as second step for CreateAndGo. + * + * \param tp transport port + * + * \return SNMP error code + */ +static int +inet_activate(struct tport *tp) +{ + struct inet_port *port = (struct inet_port *)tp; + + return (port->activate(port)); +} + +/* + * Close the SNMP port if it is open and destroy it. + * + * \param tp port to close + */ +static void +inet_destroy_port(struct tport *tp) +{ + struct inet_port *port = (struct inet_port *)tp; + + deactivate_port(port); + + trans_remove_port(tp); + + free(port->dns_addr); + free(port); +} + +/** + * If the input struct has no buffer allocated yet, do it now. If allocation + * fails, read the data into a local buffer and drop it. + * + * \param pi input struct + * + * \return -1 if allocation fails, 0 otherwise + */ +static int +inet_alloc_buf(struct port_input *pi) +{ + char drop_buf[2000]; + + if (pi->buf == NULL) { + if ((pi->buf = buf_alloc(0)) == NULL) { + (void)recvfrom(pi->fd, drop_buf, sizeof(drop_buf), + 0, NULL, NULL); + return (-1); + } + pi->buflen = buf_size(0); + } + return (0); +} + +/** + * Read message into input buffer. Get also the source address and any + * control data that is available. If the message is truncated, increment + * corresponding statistics. + * + * \param pi input object + * \param msg message object to fill + * \param cbuf control data buffer + * + * \return -1 when something goes wrong, 0 othersise + */ +static int +inet_read_msg(struct port_input *pi, struct msghdr *msg, char *cbuf) +{ + struct iovec iov[1]; + + iov[0].iov_base = pi->buf; + iov[0].iov_len = pi->buflen; + + msg->msg_name = pi->peer; + msg->msg_namelen = pi->peerlen; + msg->msg_iov = iov; + msg->msg_iovlen = 1; + msg->msg_control = cbuf; + msg->msg_controllen = RECV_CBUF_SIZE; + msg->msg_flags = 0; + + memset(cbuf, 0, RECV_CBUF_SIZE); + + const ssize_t 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; + + return (0); +} + +/* + * Input available on socket. + * + * \param tp transport port + * \param pi input struct + * + * \return number of bytes received + */ +static ssize_t +inet_recv(struct tport *tp, struct port_input *pi) +{ + struct inet_port *port = __containerof(tp, struct inet_port, tport); + struct port_sock *sock = __containerof(pi, struct port_sock, input); + + assert(port->proto == BegemotSnmpdTransportProto_udp); + + if (inet_alloc_buf(pi) == -1) + return (-1); + + char cbuf[RECV_CBUF_SIZE]; + struct msghdr msg; + + if (inet_read_msg(pi, &msg, cbuf) == -1) + return (-1); + + sock->parse_ctrl(sock, &msg); + + return (0); +} + +/* + * Send message. + * + * \param tp port + * \param buf data to send + * \param len number of bytes to send + * \param addr destination address + * \param addlen destination address length + * + * \return number of bytes sent + */ +static ssize_t +inet_send2(struct tport *tp, const u_char *buf, size_t len, + struct port_input *pi) +{ + struct inet_port *p = __containerof(tp, struct inet_port, tport); + struct port_sock *s = (pi == NULL) ? TAILQ_FIRST(&p->socks) : + __containerof(pi, struct port_sock, input); + + struct iovec iov; + + iov.iov_base = __DECONST(void*, buf); + iov.iov_len = len; + + struct msghdr msg; + + msg.msg_flags = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = (void *)pi->peer; + msg.msg_namelen = pi->peerlen; + + msg.msg_control = NULL; + msg.msg_controllen = 0; + + char cbuf[XMIT_CBUF_SIZE]; + if (s->set_ret_source) { + msg.msg_control = cbuf; + s->setsrc(s, &msg); + } + + return (sendmsg(s->input.fd, &msg, 0)); +} + +/** exported to daemon */ +const struct transport_def inet_trans = { + "inet", + OIDX_begemotSnmpdTransInet, + inet_start, + inet_stop, + inet_destroy_port, + inet_activate, + NULL, + inet_recv, + inet_send2, +}; + +struct inet_port_params { + /** index oid */ + struct asn_oid index; + + /** internet address type */ + enum InetAddressType type; + + /** internet address */ + u_char *addr; + + /** length of address */ + size_t addr_len; + + /** port number */ + uint32_t port; + + /** protocol */ + enum BegemotSnmpdTransportProto proto; +}; + +/** + * IPv4 creation stuff. Parse the index, fill socket address and creates + * a port_sock. + * + * \param port the port to create + * \param params parameters from the SNMP SET + * + * \return SNMP error + */ +static int +ipv4_create(struct inet_port *port, struct inet_port_params *params) +{ + + if (params->addr_len != 4) + return (SNMP_ERR_INCONS_VALUE); + + struct port_sock *sock = calloc(1, sizeof(struct port_sock)); + if (sock == NULL) + return (SNMP_ERR_GENERR); + + snmpd_input_init(&sock->input); + + TAILQ_INSERT_HEAD(&port->socks, sock, link); + + struct sockaddr_in *sin = + (struct sockaddr_in *)&sock->bind_addr; + + sin->sin_len = sizeof(struct sockaddr_in); + sin->sin_family = AF_INET; + sin->sin_port = htons(params->port); + memcpy(&sin->sin_addr, params->addr, 4); /* network byte order */ + + sock->port = port; + + return (SNMP_ERR_NOERROR); +} + +/* + * An IPv4 inet port is ready. Delegate to the generic code to read the data + * and react. + * + * \param fd file descriptor that is ready + * \param udata inet_port pointer + */ +static void +ipv4_input(int fd __unused, void *udata) +{ + struct port_sock *sock = udata; + + sock->input.peerlen = sizeof(struct sockaddr_in); + snmpd_input(&sock->input, &sock->port->tport); +} + +/** + * Activate an IPv4 socket. + * + * \param sock thhe socket to activate + * + * \return error code + */ +static int +ipv4_activate_sock(struct port_sock *sock) +{ + if ((sock->input.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1) { + syslog(LOG_ERR, "creating UDP4 socket: %m"); + return (SNMP_ERR_RES_UNAVAIL); + } + + const struct sockaddr_in *sin = + (const struct sockaddr_in *)&sock->bind_addr; + + if (sin->sin_addr.s_addr == INADDR_ANY) { + /* need to know from which address to return */ + static const int on = 1; + + if (setsockopt(sock->input.fd, IPPROTO_IP, IP_RECVDSTADDR, &on, + sizeof(on)) == -1) { + syslog(LOG_ERR, "setsockopt(IP_RECVDSTADDR): %m"); + (void)close(sock->input.fd); + sock->input.fd = -1; + return (SNMP_ERR_GENERR); + } + sock->set_ret_source = true; + } + + if (bind(sock->input.fd, (const struct sockaddr *)sin, sizeof(*sin))) { + if (errno == EADDRNOTAVAIL) { + (void)close(sock->input.fd); + sock->input.fd = -1; + return (SNMP_ERR_INCONS_NAME); + } + syslog(LOG_ERR, "bind: %s:%u %m", inet_ntoa(sin->sin_addr), + ntohs(sin->sin_port)); + (void)close(sock->input.fd); + sock->input.fd = -1; + return (SNMP_ERR_GENERR); + } + + if ((sock->input.id = fd_select(sock->input.fd, ipv4_input, + sock, NULL)) == NULL) { + (void)close(sock->input.fd); + sock->input.fd = -1; + return (SNMP_ERR_GENERR); + } + sock->input.peer = (struct sockaddr *)&sock->ret_dest; + + sock->parse_ctrl = ipv4_parse_ctrl; + sock->setsrc = ipv4_setsrc; + + return (SNMP_ERR_NOERROR); +} + +/** + * Open an IPv4 socket. Make the socket, bind it and put it on the select + * list. The socket struct has already been created during creation. + * + * \param p inet port + * + * \return SNMP error code + */ +static int +ipv4_activate(struct inet_port *p) +{ + struct port_sock *sock = TAILQ_FIRST(&p->socks); + assert(sock); + assert(!TAILQ_NEXT(sock, link)); + + const int ret = ipv4_activate_sock(sock); + if (ret == SNMP_ERR_NOERROR) + p->row_status = RowStatus_active; + + return (ret); +} + +/** + * Close an IPv4 socket. Keep the sock object. + * + * \param p inet port + */ +static void +ipv4_deactivate(struct inet_port *p) +{ + struct port_sock *sock = TAILQ_FIRST(&p->socks); + assert(sock); + assert(!TAILQ_NEXT(sock, link)); + + snmpd_input_close(&sock->input); + + p->row_status = RowStatus_notInService; +} + +/** + * Parse the control data received with a UDPv4 packet. This may contain + * credentials (for a local connection) and the address of the interface + * the message was received on. If there are credentials set the priv flag + * if the effective UID is zero. + * + * \param sock the sock object + * \param msg the received message + */ +static void +ipv4_parse_ctrl(struct port_sock *sock, const struct msghdr *msg) +{ + struct sockcred *cred = NULL; + + for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(msg, cmsg)) { + + if (cmsg->cmsg_level == IPPROTO_IP && + cmsg->cmsg_type == IP_RECVDSTADDR) { + memcpy(&sock->ret_source.a4, CMSG_DATA(cmsg), + sizeof(struct in_addr)); + + } else if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_CREDS) { + cred = (struct sockcred *)(void *)CMSG_DATA(cmsg); + } + } + + sock->input.priv = 0; + if (sock->input.cred && cred) + /* remote end has sent credentials */ + sock->input.priv = (cred->sc_euid == 0); +} + +/** + * Set the source address option for IPv4 sockets. + * + * \param sock socket object + * \param msg message + */ +static void +ipv4_setsrc(struct port_sock *sock, struct msghdr *msg) +{ + struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); + + /* select outgoing interface by setting source address */ + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_SENDSRCADDR; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); + memcpy(CMSG_DATA(cmsg), &sock->ret_source.a4, + sizeof(struct in_addr)); + + msg->msg_controllen = CMSG_SPACE(sizeof(struct in_addr)); +} + +/** + * Common part of IPv6 creation. This is used by both ipv6_create() and + * ipv6z_create(). + * + * \param port the table row + * \param params creation parameters + * \param scope_id scope_id (0 or from index) + * + * \return SNMP_ERR_NOERROR if port has been created, error code otherwise + */ +static int +ipv6_create_common(struct inet_port *port, struct inet_port_params *params, + u_int scope_id) +{ + struct port_sock *sock = calloc(1, sizeof(struct port_sock)); + + if (sock == NULL) + return (SNMP_ERR_GENERR); + + struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&sock->bind_addr; + + sin->sin6_len = sizeof(struct sockaddr_in6); + sin->sin6_family = AF_INET6; + sin->sin6_port = htons(params->port); + sin->sin6_flowinfo = 0; + sin->sin6_scope_id = scope_id; + + memcpy(sin->sin6_addr.s6_addr, params->addr, 16); + + if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && scope_id == 0) { + char buf[INET6_ADDRSTRLEN]; + syslog(LOG_INFO, "%s: link local address used without scope " + "index: %s", __func__, inet_ntop(AF_INET6, + &sin->sin6_addr, buf, sizeof(buf))); + free(sock); + return (SNMP_ERR_NO_CREATION); + } + + sock->port = port; + + snmpd_input_init(&sock->input); + TAILQ_INSERT_HEAD(&port->socks, sock, link); + + return (SNMP_ERR_NOERROR); +} + +/** + * IPv6 creation stuff. Parse the index, fill socket address and creates + * a port_sock. + * + * \param port the port to create + * \param params parameters from the SNMP SET + * + * \return SNMP error + */ +static int +ipv6_create(struct inet_port *port, struct inet_port_params *params) +{ + if (params->addr_len != 16) + return (SNMP_ERR_INCONS_VALUE); + + const int ret = ipv6_create_common(port, params, 0); + if (ret != SNMP_ERR_NOERROR) + return (ret); + + return (SNMP_ERR_NOERROR); +} + +/* + * An IPv6 inet port is ready. Delegate to the generic code to read the data + * and react. + * + * \param fd file descriptor that is ready + * \param udata inet_port pointer + */ +static void +ipv6_input(int fd __unused, void *udata) +{ + struct port_sock *sock = udata; + + sock->input.peerlen = sizeof(struct sockaddr_in6); + snmpd_input(&sock->input, &sock->port->tport); +} + +/** + * Activate an IPv6 socket. + * + * \param sock thhe socket to activate + * + * \return error code + */ +static int +ipv6_activate_sock(struct port_sock *sock) +{ + if ((sock->input.fd = socket(PF_INET6, SOCK_DGRAM, 0)) == -1) { + syslog(LOG_ERR, "creating UDP6 socket: %m"); + return (SNMP_ERR_RES_UNAVAIL); + } + + const struct sockaddr_in6 *sin = + (const struct sockaddr_in6 *)&sock->bind_addr; + + if (memcmp(&sin->sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0) { + /* need to know from which address to return */ + static const int on = 1; + + if (setsockopt(sock->input.fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, + &on, sizeof(on)) == -1) { + syslog(LOG_ERR, "setsockopt(IP6_PKTINFO): %m"); + (void)close(sock->input.fd); + sock->input.fd = -1; + return (SNMP_ERR_GENERR); + } + sock->set_ret_source = true; + } + + if (bind(sock->input.fd, (const struct sockaddr *)sin, sizeof(*sin))) { + if (community != COMM_INITIALIZE && errno == EADDRNOTAVAIL) { + (void)close(sock->input.fd); + sock->input.fd = -1; + return (SNMP_ERR_INCONS_NAME); + } + char buf[INET6_ADDRSTRLEN]; + syslog(LOG_ERR, "bind: %s:%u:%u %m", inet_ntop(AF_INET6, + &sin->sin6_addr, buf, sizeof(buf)), sin->sin6_scope_id, + ntohs(sin->sin6_port)); + (void)close(sock->input.fd); + sock->input.fd = -1; + return (SNMP_ERR_GENERR); + } + if ((sock->input.id = fd_select(sock->input.fd, ipv6_input, + sock, NULL)) == NULL) { + (void)close(sock->input.fd); + sock->input.fd = -1; + return (SNMP_ERR_GENERR); + } + sock->input.peer = (struct sockaddr *)&sock->ret_dest; + + sock->parse_ctrl = ipv6_parse_ctrl; + sock->setsrc = ipv6_setsrc; + + return (SNMP_ERR_NOERROR); +} + +/** + * Open an IPv6 socket. + * + * \param port inet port + * + * \return SNMP error code + */ +static int +ipv6_activate(struct inet_port *p) +{ + struct port_sock *sock = TAILQ_FIRST(&p->socks); + assert(sock); + + const int ret = ipv6_activate_sock(sock); + + if (ret == SNMP_ERR_NOERROR) + p->row_status = RowStatus_active; + return (ret); +} + +/** + * Close an IPv6 socket. Keep the sock object. + * + * \param p inet port + */ +static void +ipv6_deactivate(struct inet_port *p) +{ + struct port_sock *sock = TAILQ_FIRST(&p->socks); + assert(sock); + assert(!TAILQ_NEXT(sock, link)); + + snmpd_input_close(&sock->input); + + p->row_status = RowStatus_notInService; +} + +/** + * IPv6 specific part of message processing. The control data may contain + * credentials and packet info that contains the destination address of + * the packet. + * + * \param sock the sock object + * \param msg the received message + */ +static void +ipv6_parse_ctrl(struct port_sock *sock, const struct msghdr *msg) +{ + struct sockcred *cred = NULL; + + for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(msg, cmsg)) { + + if (cmsg->cmsg_level == IPPROTO_IPV6 && + cmsg->cmsg_type == IPV6_PKTINFO) { + const struct in6_pktinfo *info = + (const struct in6_pktinfo *)(const void *) + CMSG_DATA(cmsg); + sock->ret_source.a6.ipi6_addr = info->ipi6_addr; + sock->ret_source.a6.ipi6_ifindex = + !IN6_IS_ADDR_LINKLOCAL(&info->ipi6_addr) ? 0: + info->ipi6_ifindex; + + } else if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_CREDS) { + cred = (struct sockcred *)(void *)CMSG_DATA(cmsg); + } + } + + sock->input.priv = 0; + if (sock->input.cred && cred) + /* remote end has sent credentials */ + sock->input.priv = (cred->sc_euid == 0); +} + +/** + * Set the source address option for IPv4 sockets. + * + * \param sock socket object + * \param msg message + */ +static void +ipv6_setsrc(struct port_sock *sock, struct msghdr *msg) +{ + struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); + + /* select outgoing interface by setting source address */ + cmsg->cmsg_level = IPPROTO_IPV6; + cmsg->cmsg_type = IPV6_PKTINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + memcpy(CMSG_DATA(cmsg), &sock->ret_source.a6, + sizeof(struct in6_pktinfo)); + + msg->msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); +} + +/** + * IPv6z creation stuff. Parse the index, fill socket address and creates + * a port_sock. + * + * \param port the port to create + * \param params parameters from the SNMP SET + * + * \return SNMP error + */ +static int +ipv6z_create(struct inet_port *port, struct inet_port_params *params) +{ + if (params->addr_len != 20) + return (SNMP_ERR_INCONS_VALUE); + + u_int scope_id = 0; + for (u_int i = 16; i < 20; i++) { + scope_id <<= 8; + scope_id |= params->addr[i]; + } + + const int ret = ipv6_create_common(port, params, scope_id); + if (ret != SNMP_ERR_NOERROR) + return (ret); + + return (SNMP_ERR_NOERROR); +} + +/** + * DNS name creation stuff. Parse the index and save the string. + * This does not create a socket struct. + * + * \param port the port to create + * \param params parameters from the SNMP SET + * + * \return SNMP error + */ +static int +dns_create(struct inet_port *port, struct inet_port_params *params) +{ + if (params->addr_len > 64) + return (SNMP_ERR_INCONS_VALUE); + + if (strnlen(params->addr, params->addr_len) != + params->addr_len) + return (SNMP_ERR_INCONS_VALUE); + + if ((port->dns_addr = realloc(params->addr, + params->addr_len + 1)) == NULL) + return (SNMP_ERR_GENERR); + + port->dns_addr[params->addr_len] = '\0'; + params->addr = NULL; + + port->dns_port = htons(params->port); + + return (SNMP_ERR_NOERROR); +} + +/** + * Open sockets. This loops through all the addresses returned by getaddrinfo + * and opens a socket for each of them. + * + * \param port inet port + * + * \return SNMP error code + */ +static int +dns_activate(struct inet_port *port) +{ + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; // XXX udp-only + hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE | AI_NUMERICSERV; + + char portbuf[8]; + sprintf(portbuf, "%hu", ntohs(port->dns_port)); + + struct addrinfo *res0; + int error = getaddrinfo(port->dns_addr[0] == '\0' + ? NULL : port->dns_addr, + portbuf, &hints, &res0); + + if (error) { + syslog(LOG_ERR, "cannot resolve address '%s': %s", + port->dns_addr, gai_strerror(error)); + return (SNMP_ERR_GENERR); + } + + for (struct addrinfo *res = res0; res != NULL; res = res->ai_next) { + if (res->ai_family != AF_INET && res->ai_family != AF_INET6) + continue; + + struct port_sock *sock = calloc(1, sizeof(struct port_sock)); + if (sock == NULL) + return (SNMP_ERR_GENERR); + + snmpd_input_init(&sock->input); + sock->port = port; + + int ret = SNMP_ERR_NOERROR; + + if (res->ai_family == AF_INET) { + *(struct sockaddr_in *)&sock->bind_addr = + *(struct sockaddr_in *)(void *)res->ai_addr; + ret = ipv4_activate_sock(sock); + } else { + *(struct sockaddr_in6 *)&sock->bind_addr = + *(struct sockaddr_in6 *)(void *)res->ai_addr; + ret = ipv6_activate_sock(sock); + } + + if (ret != SNMP_ERR_NOERROR) + free(sock); + else + TAILQ_INSERT_HEAD(&port->socks, sock, link); + } + + if (!TAILQ_EMPTY(&port->socks)) + port->row_status = RowStatus_active; + + freeaddrinfo(res0); + return (SNMP_ERR_GENERR); +} + +/** + * Deactive the socket. Close all open sockets and delete all sock objects. + * + * \param port inet port + */ +static void +dns_deactivate(struct inet_port *port) +{ + while (!TAILQ_EMPTY(&port->socks)) { + struct port_sock *sock = TAILQ_FIRST(&port->socks); + TAILQ_REMOVE(&port->socks, sock, link); + snmpd_input_close(&sock->input); + free(sock); + } + port->row_status = RowStatus_notInService; +} + +static int +inet_create(struct inet_port_params *params, struct inet_port **pp) +{ + int err = SNMP_ERR_NOERROR; + struct inet_port *port = NULL; + + if (params->port > 0xffff) { + err = SNMP_ERR_NO_CREATION; + goto fail; + } + + if ((port = malloc(sizeof(*port))) == NULL) { + err = SNMP_ERR_GENERR; + goto fail; + } + memset(port, 0, sizeof(*port)); + TAILQ_INIT(&port->socks); + + port->proto = params->proto; + port->tport.index = params->index; + + switch (params->type) { + + case InetAddressType_ipv4: + port->create = ipv4_create; + port->activate = ipv4_activate; + port->deactivate = ipv4_deactivate; + break; + + case InetAddressType_ipv6: + port->create = ipv6_create; + port->activate = ipv6_activate; + port->deactivate = ipv6_deactivate; + break; + + case InetAddressType_ipv6z: + port->create = ipv6z_create; + port->activate = ipv6_activate; + port->deactivate = ipv6_deactivate; + break; + + case InetAddressType_dns: + port->create = dns_create; + port->activate = dns_activate; + port->deactivate = dns_deactivate; + break; + + default: + err = SNMP_ERR_NO_CREATION; + goto fail; + } + + if ((err = port->create(port, params)) != SNMP_ERR_NOERROR) + goto fail; + + *pp = port; + trans_insert_port(my_trans, &port->tport); + return (err); + +fail: + free(port->dns_addr); + free(port); + return (err); +} + +static int +create_and_go(struct snmp_context *ctx, struct inet_port_params *params) +{ + int err; + struct inet_port *port; + + if ((err = inet_create(params, &port)) != SNMP_ERR_NOERROR) + return (err); + + port->row_status = RowStatus_createAndGo; + ctx->scratch->ptr1 = port; + + if (community == COMM_INITIALIZE) + return (err); + + return (inet_activate(&port->tport)); +} + +static int +create_and_wait(struct snmp_context *ctx, struct inet_port_params *params) +{ + int err; + struct inet_port *port; + + if ((err = inet_create(params, &port)) != SNMP_ERR_NOERROR) + return (err); + + port->row_status = RowStatus_createAndWait; + ctx->scratch->ptr1 = port; + + return (err); +} + +/** + * This is called to set a RowStatus value in the port table during + * SET processing. + * + * When this is called during initialization time and the RowStatus is set + * to CreateAndGo, the port is actually not activated. This is done when + * the main code calls the init() for all ports later. + */ +static int +inet_port_set(struct snmp_context *ctx, struct inet_port *port, + struct inet_port_params *params, enum RowStatus nstatus) +{ + switch (nstatus) { + + case RowStatus_createAndGo: + if (port != NULL) + return (SNMP_ERR_INCONS_VALUE); + ctx->scratch->int1 = SET_CREATED; + return (create_and_go(ctx, params)); + + case RowStatus_createAndWait: + if (port != NULL) + return (SNMP_ERR_INCONS_VALUE); + ctx->scratch->int1 = SET_CREATED; + return (create_and_wait(ctx, params)); + + case RowStatus_active: + if (port == NULL) + return (SNMP_ERR_INCONS_VALUE); + + switch (port->row_status) { + + case RowStatus_notReady: + /* this can not happend */ + abort(); + + case RowStatus_notInService: + ctx->scratch->int1 = SET_ACTIVATED; + return (inet_activate(&port->tport)); + + case RowStatus_active: + return (SNMP_ERR_NOERROR); + + case RowStatus_createAndGo: + case RowStatus_createAndWait: + case RowStatus_destroy: + abort(); + } + break; + + case RowStatus_notInService: + if (port == NULL) + return (SNMP_ERR_INCONS_VALUE); + + switch (port->row_status) { + + case RowStatus_notReady: + /* this can not happend */ + abort(); + + case RowStatus_notInService: + return (SNMP_ERR_NOERROR); + + case RowStatus_active: + /* this is done during commit */ + ctx->scratch->int1 = SET_DEACTIVATE; + return (SNMP_ERR_NOERROR); + + case RowStatus_createAndGo: + case RowStatus_createAndWait: + case RowStatus_destroy: + abort(); + } + break; + + case RowStatus_destroy: + /* this is done during commit */ + ctx->scratch->int1 = SET_DESTROY; + return (SNMP_ERR_NOERROR); + + case RowStatus_notReady: + return (SNMP_ERR_WRONG_VALUE); + } + abort(); +} + +/* + * Port table + */ +int +op_snmp_trans_inet(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]; + struct inet_port *port; + struct inet_port_params params; + int ret; + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((port = (struct inet_port *)trans_next_port(my_trans, + &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &port->tport.index); + goto fetch; + + case SNMP_OP_GET: + if ((port = (struct inet_port *)trans_find_port(my_trans, + &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + goto fetch; + + case SNMP_OP_SET: + port = (struct inet_port *)trans_find_port(my_trans, + &value->var, sub); + + if (which != LEAF_begemotSnmpdTransInetStatus) + abort(); + if (!isok_RowStatus(value->v.integer)) + return (SNMP_ERR_WRONG_VALUE); + + if (index_decode(&value->var, sub, iidx, ¶ms.type, + ¶ms.addr, ¶ms.addr_len, ¶ms.port, + ¶ms.proto)) + return (SNMP_ERR_NO_CREATION); + + asn_slice_oid(¶ms.index, &value->var, sub, value->var.len); + + ret = inet_port_set(ctx, port, ¶ms, + (enum RowStatus)value->v.integer); + + free(params.addr); + return (ret); + + case SNMP_OP_ROLLBACK: + if ((port = (struct inet_port *)trans_find_port(my_trans, + &value->var, sub)) == NULL) + /* cannot happen */ + abort(); + + switch (ctx->scratch->int1) { + + case SET_CREATED: + /* newly created */ + assert(port != NULL); + inet_destroy_port(&port->tport); + return (SNMP_ERR_NOERROR); + + case SET_DESTROY: + /* do it now */ + assert(port != NULL); + return (SNMP_ERR_NOERROR); + + case SET_ACTIVATED: + deactivate_port(port); + return (SNMP_ERR_NOERROR); + + case SET_DEACTIVATE: + return (SNMP_ERR_NOERROR); + } + abort(); + + case SNMP_OP_COMMIT: + if ((port = (struct inet_port *)trans_find_port(my_trans, + &value->var, sub)) == NULL) + /* cannot happen */ + abort(); + + switch (ctx->scratch->int1) { + + case SET_CREATED: + /* newly created */ + assert(port != NULL); + return (SNMP_ERR_NOERROR); + + case SET_DESTROY: + /* do it now */ + assert(port != NULL); + inet_destroy_port(&port->tport); + return (SNMP_ERR_NOERROR); + + case SET_ACTIVATED: + return (SNMP_ERR_NOERROR); + + case SET_DEACTIVATE: + deactivate_port(port); + return (SNMP_ERR_NOERROR); + } + abort(); + } + abort(); + + fetch: + switch (which) { + + case LEAF_begemotSnmpdTransInetStatus: + value->v.integer = port->row_status; + break; + + default: + abort(); + } + + return (SNMP_ERR_NOERROR); +} Property changes on: vendor/bsnmp/dist/snmpd/trans_inet.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/bsnmp/dist/snmpd/trans_inet.h =================================================================== --- vendor/bsnmp/dist/snmpd/trans_inet.h (nonexistent) +++ vendor/bsnmp/dist/snmpd/trans_inet.h (revision 359490) @@ -0,0 +1,38 @@ +/* + * Copyright (c) 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. + * + * $Id$ + */ + +#ifndef trans_inet_h_1530971397 +#define trans_inet_h_1530971397 + +/* transport declaration */ +extern const struct transport_def inet_trans; + +#endif Property changes on: vendor/bsnmp/dist/snmpd/trans_inet.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/bsnmp/dist/snmpd/trans_lsock.c =================================================================== --- vendor/bsnmp/dist/snmpd/trans_lsock.c (revision 359489) +++ vendor/bsnmp/dist/snmpd/trans_lsock.c (revision 359490) @@ -1,669 +1,670 @@ /* * 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 + lsock_recv, + NULL }; 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); } Index: vendor/bsnmp/dist/snmpd/trans_udp.c =================================================================== --- vendor/bsnmp/dist/snmpd/trans_udp.c (revision 359489) +++ vendor/bsnmp/dist/snmpd/trans_udp.c (revision 359490) @@ -1,438 +1,439 @@ /* * 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 + udp_recv, + NULL }; 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); } Index: vendor/bsnmp/dist/snmpd/trap.c =================================================================== --- vendor/bsnmp/dist/snmpd/trap.c (revision 359489) +++ vendor/bsnmp/dist/snmpd/trap.c (revision 359490) @@ -1,910 +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" + +#define SNMPTREE_TYPES #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; + sa.sin_port = htons(addrs->address[4] << 8 | addrs->address[5]); 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); } Index: vendor/bsnmp/dist/snmpd/tree.def =================================================================== --- vendor/bsnmp/dist/snmpd/tree.def (revision 359489) +++ vendor/bsnmp/dist/snmpd/tree.def (revision 359490) @@ -1,214 +1,233 @@ # # Copyright (c) 2001-2003 # Fraunhofer Institute for Open Communication Systems (FhG Fokus). # All rights reserved. # +# Copyright (c) 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: tree.def 517 2006-10-31 08:52:04Z brandt_h $ # # System group and private Begemot SNMPd MIB. # include "tc.def" +typedef BegemotSnmpdTransportProto ENUM ( + 1 udp +) + (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) + (4 begemotSnmpdTransInet OID op_transport_dummy) ) + (11 begemotSnmpdTransInetTable + (1 begemotSnmpdTransInetEntry : INTEGER OCTETSTRING INTEGER INTEGER op_snmp_trans_inet + (1 begemotSnmpdTransInetAddressType InetAddressType) + (2 begemotSnmpdTransInetAddress OCTETSTRING) + (3 begemotSnmpdTransInetPort INTEGER) + (4 begemotSnmpdTransInetProto BegemotSnmpdTransportProto) + (5 begemotSnmpdTransInetStatus RowStatus GET SET) + + )) ) (2 begemotSnmpdDefs (1 begemotSnmpdAgent (1 begemotSnmpdAgentFreeBSD OID op_dummy) ) ) + (3 begemotSnmpdCompliance) ) )) ) ) (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) ) ) ) )) ) Index: vendor/bsnmp/dist/tests/asn1.cc =================================================================== --- vendor/bsnmp/dist/tests/asn1.cc (nonexistent) +++ vendor/bsnmp/dist/tests/asn1.cc (revision 359490) @@ -0,0 +1,1041 @@ +/* + * Copyright (c) 2020 + * Hartmut Brandt + * All rights reserved. + * + * 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. + * + * :se ts=4 + */ + +#include "constbuf.h" + +extern "C" { +#include "asn1.h" +} + +#include "catch.hpp" + +#include +#include +#include +#include +#include +#include + +using namespace test::literals; + +template +static std::enable_if_t, asn_buf> +mk_asn_buf(const T &b) +{ + asn_buf abuf; + + abuf.asn_cptr = b.data(); + abuf.asn_len = b.size(); + + return abuf; +} + +static asn_buf +mk_asn_buf(asn_len_t len) +{ + asn_buf abuf; + + abuf.asn_ptr = new u_char[len]; + abuf.asn_len = len; + + return abuf; +} + +static std::string g_errstr; + +static void +save_g_errstr(const struct asn_buf *b, const char *fmt, ...) +{ + va_list ap; + + char sbuf[20000]; + va_start(ap, fmt); + vsprintf(sbuf, fmt, ap); + va_end(ap); + + if (b != NULL) { + strcat(sbuf, " at"); + for (u_int i = 0; b->asn_len > i; i++) + sprintf(sbuf + strlen(sbuf), " %02x", b->asn_cptr[i]); + } + strcat(sbuf, "\n"); + + g_errstr = sbuf; +} + +/** + * Encapsulate an ASN.1 parse buffer and the parse header fields. + * Constructing parses the header. + */ +struct Asn_value +{ + /** parse buffer */ + struct asn_buf buf; + + /** error from header parsing */ + asn_err err; + + /** ASN.1 tag byte */ + uint8_t type; + + /** value length */ + asn_len_t alen; + + /** + * Construct a parse buffer and parse the header. + * + * \tparam Tbuf input buffer type + * + * \param ibuf input buffer + */ + template + explicit + Asn_value(const Tbuf &ibuf) + : buf {mk_asn_buf(ibuf)}, err {asn_get_header(&buf, &type, &alen)} + { + } +}; + +/** + * Parse the ASN.1 header and check the error code. If the error is not + * ASN_ERR_OK then check the error string. + * + * \tparam Tbuf input buffer type + * + * \param buf input buffer + * \param err expected error code (default ASN_ERR_OK) + * \param errstr expected error string (default empty) + * + * \return the parse buffer + */ +template +static auto +check_header(const Tbuf &buf, asn_err err = ASN_ERR_OK, + std::string_view errstr = {}) +{ + g_errstr.clear(); + auto r = Asn_value(buf); + REQUIRE(r.err == err); + if (r.err != ASN_ERR_OK) + REQUIRE(g_errstr == errstr); + else + REQUIRE(g_errstr == ""); + return r; +} + +/** + * Parse the ASN.1 header and expect it not to fail. The check the tag. + * + * \tparam Tbuf input buffer type + * + * \param buf input buffer + * \param tag expected type tag + * + * \return the parse buffer + */ +template +static auto +check_header(const Tbuf &buf, uint8_t type) +{ + auto r = check_header(buf); + REQUIRE(r.type == type); + return r; +} + +/** + * Parse the ASN.1 header and expect it not to fail. The check the tag and + * the length. + * + * \tparam Tbuf input buffer type + * + * \param buf input buffer + * \param tag expected type tag + * \param alen expected value length + * + * \return the parse buffer + */ +template +static auto +check_header(const Tbuf &buf, uint8_t type, asn_len_t alen) +{ + auto r = check_header(buf); + REQUIRE(r.type == type); + REQUIRE(r.alen == alen); + return r; +} + +template +static void +check_buf(const asn_buf &s, const Tbuf &exp, bool print = false) +{ + if (print) { + for (auto c : exp) + std::printf(":%02x", c); + std::printf("\n"); + + for (size_t i = 0; i < size(exp); i++) + std::printf(":%02x", s.asn_ptr[i]); + std::printf("\n"); + } + REQUIRE(std::equal(begin(exp), end(exp), s.asn_ptr)); +} + +TEST_CASE("ASN.1 header parsing", "[asn1][parse]") +{ + asn_error = save_g_errstr; + + SECTION("empty buffer") { + check_header(std::vector{}, ASN_ERR_EOBUF, + "no identifier for header at\n"); + } + SECTION("tag too large") { + check_header("x1f:06:01:7f"_cbuf, ASN_ERR_FAILED, + "tags > 0x1e not supported (0x1f) at 1f 06 01 7f\n"); + } + SECTION("no length field") { + check_header("x46"_cbuf, ASN_ERR_EOBUF, "no length field at\n"); + } + SECTION("indefinite length") { + check_header("x46:80:02:04:06"_cbuf, ASN_ERR_FAILED, + "indefinite length not supported at 02 04 06\n"); + } + SECTION("long length") { + check_header("x46:83:00:00:02:7f:12"_cbuf, ASN_ERR_FAILED, + "long length too long (3) at 00 00 02 7f 12\n"); + } + SECTION("truncated length field") { + check_header("x46:82:00"_cbuf, ASN_ERR_EOBUF, + "long length truncated at 00\n"); + } + SECTION("correct long length") { + check_header("x04:81:00"_cbuf, ASN_TYPE_OCTETSTRING, 0); +#ifndef BOGUS_CVE_2019_5610_FIX + check_header("x04:81:04:00"_cbuf, ASN_TYPE_OCTETSTRING, 4); + check_header("x04:81:ff:00"_cbuf, ASN_TYPE_OCTETSTRING, 255); +#endif + check_header("x04:82:00:00"_cbuf, ASN_TYPE_OCTETSTRING, 0); +#ifndef BOGUS_CVE_2019_5610_FIX + check_header("x04:82:00:80"_cbuf, ASN_TYPE_OCTETSTRING, 128); + check_header("x04:82:01:80"_cbuf, ASN_TYPE_OCTETSTRING, 384); + check_header("x04:82:ff:ff"_cbuf, ASN_TYPE_OCTETSTRING, 65535); +#endif + } + SECTION("short length") { + check_header("x04:00:00"_cbuf, ASN_TYPE_OCTETSTRING, 0); + check_header("x04:01:00"_cbuf, ASN_TYPE_OCTETSTRING, 1); +#ifndef BOGUS_CVE_2019_5610_FIX + check_header("x04:40:00"_cbuf, ASN_TYPE_OCTETSTRING, 64); + check_header("x04:7f:00"_cbuf, ASN_TYPE_OCTETSTRING, 127); +#endif + } +} + +TEST_CASE("ASN.1 header building", "[asn1][build]") +{ + asn_error = save_g_errstr; + + const auto conv_err = [] (asn_len_t alen, asn_len_t vlen, uint8_t type, + asn_err err, std::string_view errstr) { + auto b = mk_asn_buf(alen); + g_errstr.clear(); + REQUIRE(asn_put_header(&b, type, vlen) == err); + REQUIRE(g_errstr == errstr); + }; + + const auto conv = [] (asn_len_t alen, asn_len_t vlen, uint8_t type, + const auto &cbuf) { + auto b = mk_asn_buf(alen); + auto t = b; + REQUIRE(asn_put_header(&b, type, vlen) == ASN_ERR_OK); + REQUIRE(b.asn_len == (size_t)0); + check_buf(t, cbuf); + }; + + SECTION("no space for tag") { + conv_err(0, 0, ASN_TYPE_OCTETSTRING, ASN_ERR_EOBUF, ""); + } + SECTION("no space for length") { + conv_err(1, 0, ASN_TYPE_OCTETSTRING, ASN_ERR_EOBUF, ""); + conv_err(2, 128, ASN_TYPE_OCTETSTRING, ASN_ERR_EOBUF, ""); + } + SECTION("bad tag") { + conv_err(2, 0, 0x1f, ASN_ERR_FAILED, + "types > 0x1e not supported (0x1f)\n"); + conv_err(2, 0, 0xff, ASN_ERR_FAILED, + "types > 0x1e not supported (0x1f)\n"); + } + SECTION("ok") { + conv(2, 0, ASN_TYPE_OCTETSTRING, "x04:00"_cbuf); + } +} + +TEST_CASE("Counter64 parsing", "[asn1][parse]") +{ + asn_error = save_g_errstr; + + /** + * Sucessfully parse a COUNTER64 value. + * + * \param buf buffer to parse + * \param xval expected value + */ + const auto conv = [] (const auto &buf, uint64_t xval) { + auto r = check_header(buf, ASN_APP_COUNTER64 | ASN_CLASS_APPLICATION); + + uint64_t val; + REQUIRE(asn_get_counter64_raw(&r.buf, r.alen, &val) == ASN_ERR_OK); + REQUIRE(val == xval); + }; + + /** + * Parse COUNTER64 with error. + * + * \param buf buffer to parse + * \param err expected error from value parser + * \param errstr expected error string + */ + const auto conv_err = [] (const auto &buf, asn_err err, + std::string_view errstr) { + auto r = check_header(buf, ASN_APP_COUNTER64 | ASN_CLASS_APPLICATION); + + g_errstr.clear(); + uint64_t val; + REQUIRE(asn_get_counter64_raw(&r.buf, r.alen, &val) == err); + REQUIRE(g_errstr == errstr); + }; + + SECTION("correct encoding") { + + conv("x46:01:00"_cbuf, 0x0ULL); + conv("x46:01:01"_cbuf, 0x1ULL); + conv("x46:01:7f"_cbuf, 0x7fULL); + + conv("x46:02:00:80"_cbuf, 0x80ULL); + conv("x46:02:00:ff"_cbuf, 0xffULL); + conv("x46:02:7f:ff"_cbuf, 0x7fffULL); + + conv("x46:03:00:80:00"_cbuf, 0x8000ULL); + conv("x46:03:00:ff:ff"_cbuf, 0xffffULL); + conv("x46:03:7f:ff:ff"_cbuf, 0x7fffffULL); + + conv("x46:04:00:80:00:00"_cbuf, 0x800000ULL); + conv("x46:04:00:ff:ff:ff"_cbuf, 0xffffffULL); + conv("x46:04:7f:ff:ff:ff"_cbuf, 0x7fffffffULL); + + conv("x46:05:00:80:00:00:00"_cbuf, 0x80000000ULL); + conv("x46:05:00:ff:ff:ff:ff"_cbuf, 0xffffffffULL); + conv("x46:05:7f:ff:ff:ff:ff"_cbuf, 0x7fffffffffULL); + + conv("x46:06:00:80:00:00:00:00"_cbuf, 0x8000000000ULL); + conv("x46:06:00:ff:ff:ff:ff:ff"_cbuf, 0xffffffffffULL); + conv("x46:06:7f:ff:ff:ff:ff:ff"_cbuf, 0x7fffffffffffULL); + + conv("x46:07:00:80:00:00:00:00:00"_cbuf, 0x800000000000ULL); + conv("x46:07:00:ff:ff:ff:ff:ff:ff"_cbuf, 0xffffffffffffULL); + conv("x46:07:7f:ff:ff:ff:ff:ff:ff"_cbuf, 0x7fffffffffffffULL); + + conv("x46:08:00:80:00:00:00:00:00:00"_cbuf, 0x80000000000000ULL); + conv("x46:08:00:ff:ff:ff:ff:ff:ff:ff"_cbuf, 0xffffffffffffffULL); + conv("x46:08:7f:ff:ff:ff:ff:ff:ff:ff"_cbuf, 0x7fffffffffffffffULL); + + conv("x46:09:00:80:00:00:00:00:00:00:00"_cbuf, 0x8000000000000000ULL); + conv("x46:09:00:ff:ff:ff:ff:ff:ff:ff:ff"_cbuf, 0xffffffffffffffffULL); + } + + SECTION("zero length") { + conv_err("x46:00"_cbuf, ASN_ERR_BADLEN, + "zero-length integer at\n"); + } + + SECTION("non minimal encoding") { + conv_err("x46:02:00:00"_cbuf, ASN_ERR_BADLEN, + "non-minimal unsigned at 00 00\n"); + conv_err("x46:02:00:7f"_cbuf, ASN_ERR_BADLEN, + "non-minimal unsigned at 00 7f\n"); + conv_err("x46:03:00:00:80"_cbuf, ASN_ERR_BADLEN, + "non-minimal unsigned at 00 00 80\n"); + conv_err("x46:04:00:00:80:00"_cbuf, ASN_ERR_BADLEN, + "non-minimal unsigned at 00 00 80 00\n"); + conv_err("x46:0a:00:00:00:00:00:00:00:00:00:00"_cbuf, ASN_ERR_BADLEN, + "non-minimal unsigned at 00 00 00 00 00 00 00 00 00 00\n"); + conv_err("x46:0a:00:01:00:00:00:00:00:00:00:00"_cbuf, ASN_ERR_BADLEN, + "non-minimal unsigned at 00 01 00 00 00 00 00 00 00 00\n"); + } + + SECTION("out of range") { + conv_err("x46:09:01:00:00:00:00:00:00:00:00"_cbuf, ASN_ERR_RANGE, + "unsigned too large or negative at 01 00 00 00 00 00 00 00 00\n"); + conv_err("x46:0a:01:00:00:00:00:00:00:00:00:00"_cbuf, ASN_ERR_RANGE, + "unsigned too large or negative at 01 00 00 00 00 00 00 00 00 00\n"); + conv_err("x46:01:80"_cbuf, ASN_ERR_RANGE, + "unsigned too large or negative at 80\n"); + conv_err("x46:02:80:00"_cbuf, ASN_ERR_RANGE, + "unsigned too large or negative at 80 00\n"); + conv_err("x46:03:80:00:00"_cbuf, ASN_ERR_RANGE, + "unsigned too large or negative at 80 00 00\n"); + } + +#ifndef BOGUS_CVE_2019_5610_FIX + SECTION("truncated value") { + conv_err("x46:02:00"_cbuf, ASN_ERR_EOBUF, + "truncated integer at 00\n"); + conv_err("x46:09:00:80:00:00:00"_cbuf, ASN_ERR_EOBUF, + "truncated integer at 00 80 00 00 00\n"); + conv_err("x46:09:00:ff:ff:ff:ff:ff:ff:ff"_cbuf, ASN_ERR_EOBUF, + "truncated integer at 00 ff ff ff ff ff ff ff\n"); + } +#endif +} + +TEST_CASE("Counter64 building", "[asn1][build]") +{ + asn_error = save_g_errstr; + + const auto conv = [] (asn_len_t alen, uint64_t val, const auto &buf) { + auto b = mk_asn_buf(alen); + auto s = b; + REQUIRE(asn_put_counter64(&b, val) == ASN_ERR_OK); + REQUIRE(b.asn_len == (size_t)0); + check_buf(s, buf); + }; + + const auto conv_err = [] (asn_len_t alen, uint64_t val, asn_err err, + std::string_view errstr) { + auto b = mk_asn_buf(alen); + g_errstr.clear(); + REQUIRE(asn_put_counter64(&b, val) == err); + REQUIRE(g_errstr == errstr); + }; + + conv(3, 0x0, "x46:01:00"_cbuf); + conv(3, 0x1, "x46:01:01"_cbuf); + conv(3, 0x7f, "x46:01:7f"_cbuf); + + conv(4, 0x80, "x46:02:00:80"_cbuf); + conv(4, 0xff, "x46:02:00:ff"_cbuf); + conv(4, 0x7fff, "x46:02:7f:ff"_cbuf); + + conv(5, 0x8000, "x46:03:00:80:00"_cbuf); + conv(5, 0xffff, "x46:03:00:ff:ff"_cbuf); + conv(5, 0x7fffff, "x46:03:7f:ff:ff"_cbuf); + + conv(6, 0x800000, "x46:04:00:80:00:00"_cbuf); + conv(6, 0xffffff, "x46:04:00:ff:ff:ff"_cbuf); + conv(6, 0x7fffffff, "x46:04:7f:ff:ff:ff"_cbuf); + + conv(7, 0x80000000, "x46:05:00:80:00:00:00"_cbuf); + conv(7, 0xffffffff, "x46:05:00:ff:ff:ff:ff"_cbuf); + conv(7, 0x7fffffffff, "x46:05:7f:ff:ff:ff:ff"_cbuf); + + conv(8, 0x8000000000, "x46:06:00:80:00:00:00:00"_cbuf); + conv(8, 0xffffffffff, "x46:06:00:ff:ff:ff:ff:ff"_cbuf); + conv(8, 0x7fffffffffff, "x46:06:7f:ff:ff:ff:ff:ff"_cbuf); + + conv(9, 0x800000000000, "x46:07:00:80:00:00:00:00:00"_cbuf); + conv(9, 0xffffffffffff, "x46:07:00:ff:ff:ff:ff:ff:ff"_cbuf); + conv(9, 0x7fffffffffffff, "x46:07:7f:ff:ff:ff:ff:ff:ff"_cbuf); + + conv(10, 0x80000000000000, "x46:08:00:80:00:00:00:00:00:00"_cbuf); + conv(10, 0xffffffffffffff, "x46:08:00:ff:ff:ff:ff:ff:ff:ff"_cbuf); + conv(10, 0x7fffffffffffffff, "x46:08:7f:ff:ff:ff:ff:ff:ff:ff"_cbuf); + + conv(11, 0x8000000000000000, "x46:09:00:80:00:00:00:00:00:00:00"_cbuf); + conv(11, 0xffffffffffffffff, "x46:09:00:ff:ff:ff:ff:ff:ff:ff:ff"_cbuf); + + SECTION("empty buffer") { + conv_err(0, 0, ASN_ERR_EOBUF, ""); + } + SECTION("buffer too short for length field") { + conv_err(1, 0, ASN_ERR_EOBUF, ""); + } + SECTION("buffer too short") { + conv_err(2, 0, ASN_ERR_EOBUF, ""); + conv_err(3, 0x80, ASN_ERR_EOBUF, ""); + conv_err(4, 0x8000, ASN_ERR_EOBUF, ""); + conv_err(5, 0x800000, ASN_ERR_EOBUF, ""); + conv_err(6, 0x80000000, ASN_ERR_EOBUF, ""); + conv_err(7, 0x8000000000, ASN_ERR_EOBUF, ""); + conv_err(8, 0x800000000000, ASN_ERR_EOBUF, ""); + conv_err(9, 0x80000000000000, ASN_ERR_EOBUF, ""); + conv_err(10, 0x8000000000000000, ASN_ERR_EOBUF, ""); + } +} + +TEST_CASE("Unsigned32 parsing", "[asn1][parse]") +{ + asn_error = save_g_errstr; + + /** + * Sucessfully parse a COUNTER value. + * + * \param buf buffer to parse + * \param xval expected value + */ + const auto conv = [] (const auto &buf, uint32_t xval) { + auto r = check_header(buf, ASN_APP_COUNTER | ASN_CLASS_APPLICATION); + + uint32_t val; + REQUIRE(asn_get_uint32_raw(&r.buf, r.alen, &val) == ASN_ERR_OK); + REQUIRE(val == xval); + }; + + /** + * Parse COUNTER with error. + * + * \param buf buffer to parse + * \param err expected error from value parser + * \param errstr expected error string + */ + const auto conv_err = [] (const auto &buf, asn_err err, + std::string_view errstr) { + auto r = check_header(buf, ASN_APP_COUNTER | ASN_CLASS_APPLICATION); + + g_errstr.clear(); + uint32_t val; + REQUIRE(asn_get_uint32_raw(&r.buf, r.alen, &val) == err); + REQUIRE(g_errstr == errstr); + }; + + SECTION("correct encoding") { + conv("x41:01:00"_cbuf, 0x0U); + conv("x41:01:01"_cbuf, 0x1U); + conv("x41:01:7f"_cbuf, 0x7fU); + + conv("x41:02:00:80"_cbuf, 0x80U); + conv("x41:02:00:ff"_cbuf, 0xffU); + conv("x41:02:7f:ff"_cbuf, 0x7fffU); + + conv("x41:03:00:80:00"_cbuf, 0x8000U); + conv("x41:03:00:ff:ff"_cbuf, 0xffffU); + conv("x41:03:7f:ff:ff"_cbuf, 0x7fffffU); + + conv("x41:04:00:80:00:00"_cbuf, 0x800000U); + conv("x41:04:00:ff:ff:ff"_cbuf, 0xffffffU); + conv("x41:04:7f:ff:ff:ff"_cbuf, 0x7fffffffU); + + conv("x41:05:00:80:00:00:00"_cbuf, 0x80000000U); + conv("x41:05:00:ff:ff:ff:ff"_cbuf, 0xffffffffU); + } + SECTION("zero length") { + + conv_err("x41:00"_cbuf, ASN_ERR_BADLEN, + "zero-length integer at\n"); + } + + SECTION("non minimal encoding") { + conv_err("x41:02:00:00"_cbuf, ASN_ERR_BADLEN, + "non-minimal unsigned at 00 00\n"); + conv_err("x41:02:00:7f"_cbuf, ASN_ERR_BADLEN, + "non-minimal unsigned at 00 7f\n"); + conv_err("x41:03:00:00:80"_cbuf, ASN_ERR_BADLEN, + "non-minimal unsigned at 00 00 80\n"); + conv_err("x41:04:00:00:80:00"_cbuf, ASN_ERR_BADLEN, + "non-minimal unsigned at 00 00 80 00\n"); + conv_err("x41:06:00:00:00:00:00:00"_cbuf, ASN_ERR_BADLEN, + "non-minimal unsigned at 00 00 00 00 00 00\n"); + conv_err("x41:06:00:01:00:00:00:00"_cbuf, ASN_ERR_BADLEN, + "non-minimal unsigned at 00 01 00 00 00 00\n"); + } + + SECTION("out of range") { + conv_err("x41:05:01:00:00:00:00"_cbuf, + ASN_ERR_RANGE, "uint32 too large 4294967296 at\n"); + conv_err("x41:06:01:00:00:00:00:00"_cbuf, + ASN_ERR_RANGE, "uint32 too large 1099511627776 at\n"); + conv_err("x41:01:80"_cbuf, + ASN_ERR_RANGE, "unsigned too large or negative at 80\n"); + conv_err("x41:02:80:00"_cbuf, + ASN_ERR_RANGE, "unsigned too large or negative at 80 00\n"); + conv_err("x41:03:80:00:00"_cbuf, + ASN_ERR_RANGE, "unsigned too large or negative at 80 00 00\n"); + } + +#ifndef BOGUS_CVE_2019_5610_FIX + SECTION("truncated value") { + conv_err("x41:01"_cbuf, ASN_ERR_EOBUF, + "truncated integer at\n"); + conv_err("x41:02:01"_cbuf, ASN_ERR_EOBUF, + "truncated integer at 01\n"); + conv_err("x41:05:00:80:"_cbuf, ASN_ERR_EOBUF, + "truncated integer at 00 80\n"); + conv_err("x41:05:00:ff:ff:ff"_cbuf, ASN_ERR_EOBUF, + "truncated integer at 00 ff ff ff\n"); + } +#endif +} + +TEST_CASE("Unsigned32 building", "[asn1][build]") +{ + asn_error = save_g_errstr; + + const auto conv = [] (asn_len_t alen, uint32_t val, const auto &buf) { + auto b = mk_asn_buf(alen); + auto s = b; + REQUIRE(asn_put_uint32(&b, ASN_APP_COUNTER, val) == ASN_ERR_OK); + REQUIRE(b.asn_len == (size_t)0); + check_buf(s, buf); + }; + + const auto conv_err = [] (asn_len_t alen, uint32_t val, asn_err err, + std::string_view errstr) { + auto b = mk_asn_buf(alen); + g_errstr.clear(); + REQUIRE(asn_put_uint32(&b, ASN_APP_COUNTER, val) == err); + REQUIRE(g_errstr == errstr); + }; + + conv(3, 0x0, "x41:01:00"_cbuf); + conv(3, 0x1, "x41:01:01"_cbuf); + conv(3, 0x7f, "x41:01:7f"_cbuf); + + conv(4, 0x80, "x41:02:00:80"_cbuf); + conv(4, 0xff, "x41:02:00:ff"_cbuf); + conv(4, 0x7fff, "x41:02:7f:ff"_cbuf); + + conv(5, 0x8000, "x41:03:00:80:00"_cbuf); + conv(5, 0xffff, "x41:03:00:ff:ff"_cbuf); + conv(5, 0x7fffff, "x41:03:7f:ff:ff"_cbuf); + + conv(6, 0x800000, "x41:04:00:80:00:00"_cbuf); + conv(6, 0xffffff, "x41:04:00:ff:ff:ff"_cbuf); + conv(6, 0x7fffffff, "x41:04:7f:ff:ff:ff"_cbuf); + + conv(7, 0x80000000, "x41:05:00:80:00:00:00"_cbuf); + conv(7, 0xffffffff, "x41:05:00:ff:ff:ff:ff"_cbuf); + + SECTION("empty buffer") { + conv_err(0, 0, ASN_ERR_EOBUF, ""); + } + SECTION("buffer too short for length field") { + conv_err(1, 0, ASN_ERR_EOBUF, ""); + } + SECTION("buffer too short") { + conv_err(2, 0, ASN_ERR_EOBUF, ""); + conv_err(3, 0x80, ASN_ERR_EOBUF, ""); + conv_err(4, 0x8000, ASN_ERR_EOBUF, ""); + conv_err(5, 0x800000, ASN_ERR_EOBUF, ""); + conv_err(6, 0x80000000, ASN_ERR_EOBUF, ""); + } +} + +TEST_CASE("Integer parsing", "[asn1][parse]") +{ + asn_error = save_g_errstr; + + /** + * Sucessfully parse a INTEGER value. + * + * \param buf buffer to parse + * \param xval expected value + */ + const auto conv = [] (const auto &buf, int32_t xval) { + auto r = check_header(buf, ASN_TYPE_INTEGER); + + int32_t val; + REQUIRE(asn_get_integer_raw(&r.buf, r.alen, &val) == ASN_ERR_OK); + REQUIRE(val == xval); + }; + + /** + * Parse INTEGER with error. + * + * \param buf buffer to parse + * \param err expected error from value parser + * \param errstr expected error string + */ + const auto conv_err = [] (const auto &buf, asn_err err, + std::string_view errstr) { + auto r = check_header(buf, ASN_TYPE_INTEGER); + + g_errstr.clear(); + int32_t val; + REQUIRE(asn_get_integer_raw(&r.buf, r.alen, &val) == err); + REQUIRE(g_errstr == errstr); + }; + + SECTION("correct encoding") { + conv("x02:01:00"_cbuf, 0x0); + conv("x02:01:01"_cbuf, 0x1); + conv("x02:01:7f"_cbuf, 0x7f); + conv("x02:01:ff"_cbuf, -0x1); + conv("x02:01:80"_cbuf, -0x80); + + conv("x02:02:00:80"_cbuf, 0x80); + conv("x02:02:00:ff"_cbuf, 0xff); + conv("x02:02:7f:ff"_cbuf, 0x7fff); + conv("x02:02:ff:7f"_cbuf, -0x81); + conv("x02:02:ff:01"_cbuf, -0xff); + conv("x02:02:ff:00"_cbuf, -0x100); + conv("x02:02:80:00"_cbuf, -0x8000); + + conv("x02:03:00:80:00"_cbuf, 0x8000); + conv("x02:03:00:ff:ff"_cbuf, 0xffff); + conv("x02:03:7f:ff:ff"_cbuf, 0x7fffff); + conv("x02:03:ff:7f:ff"_cbuf, -0x8001); + conv("x02:03:ff:00:01"_cbuf, -0xffff); + conv("x02:03:ff:00:00"_cbuf, -0x10000); + conv("x02:03:80:00:00"_cbuf, -0x800000); + + conv("x02:04:00:80:00:00"_cbuf, 0x800000); + conv("x02:04:00:ff:ff:ff"_cbuf, 0xffffff); + conv("x02:04:7f:ff:ff:ff"_cbuf, 0x7fffffff); + conv("x02:04:ff:7f:ff:ff"_cbuf, -0x800001); + conv("x02:04:ff:00:00:01"_cbuf, -0xffffff); + conv("x02:04:ff:00:00:00"_cbuf, -0x1000000); + conv("x02:04:80:00:00:00"_cbuf, -0x80000000); + } + + SECTION("zero length") { + conv_err("x02:00"_cbuf, ASN_ERR_BADLEN, + "zero-length integer at\n"); + } + SECTION("too long") { + conv_err("x02:05:01:02:03:04:05"_cbuf, ASN_ERR_BADLEN, + "integer too long at\n"); + } + + SECTION("non minimal encoding") { + conv_err("x02:02:00:00"_cbuf, ASN_ERR_BADLEN, + "non-minimal integer at 00 00\n"); + conv_err("x02:02:00:7f"_cbuf, ASN_ERR_BADLEN, + "non-minimal integer at 00 7f\n"); + conv_err("x02:03:00:00:80"_cbuf, ASN_ERR_BADLEN, + "non-minimal integer at 00 00 80\n"); + conv_err("x02:04:00:00:80:00"_cbuf, ASN_ERR_BADLEN, + "non-minimal integer at 00 00 80 00\n"); + conv_err("x02:06:00:00:00:00:00:00"_cbuf, ASN_ERR_BADLEN, + "non-minimal integer at 00 00 00 00 00 00\n"); + conv_err("x02:06:00:01:00:00:00:00"_cbuf, ASN_ERR_BADLEN, + "non-minimal integer at 00 01 00 00 00 00\n"); + conv_err("x02:02:ff:80"_cbuf, ASN_ERR_BADLEN, + "non-minimal integer at ff 80\n"); + conv_err("x02:02:ff:ff"_cbuf, ASN_ERR_BADLEN, + "non-minimal integer at ff ff\n"); + conv_err("x02:03:ff:80:00"_cbuf, ASN_ERR_BADLEN, + "non-minimal integer at ff 80 00\n"); + conv_err("x02:03:ff:ff:ff"_cbuf, ASN_ERR_BADLEN, + "non-minimal integer at ff ff ff\n"); + conv_err("x02:04:ff:80:00:00"_cbuf, ASN_ERR_BADLEN, + "non-minimal integer at ff 80 00 00\n"); + conv_err("x02:04:ff:ff:ff:ff"_cbuf, ASN_ERR_BADLEN, + "non-minimal integer at ff ff ff ff\n"); + conv_err("x02:06:ff:80:00:00:00:00"_cbuf, ASN_ERR_BADLEN, + "non-minimal integer at ff 80 00 00 00 00\n"); + conv_err("x02:06:ff:ff:ff:ff:ff:ff"_cbuf, ASN_ERR_BADLEN, + "non-minimal integer at ff ff ff ff ff ff\n"); + } + +#ifndef BOGUS_CVE_2019_5610_FIX + SECTION("truncated value") { + conv_err("x02:01"_cbuf, ASN_ERR_EOBUF, + "truncated integer at\n"); + conv_err("x02:02:ff"_cbuf, ASN_ERR_EOBUF, + "truncated integer at ff\n"); + conv_err("x02:05:ff:00:03:01"_cbuf, ASN_ERR_EOBUF, + "truncated integer at ff 00 03 01\n"); + conv_err("x02:04:7f:ff:"_cbuf, ASN_ERR_EOBUF, + "truncated integer at 7f ff\n"); + conv_err("x02:04:80:00:00"_cbuf, ASN_ERR_EOBUF, + "truncated integer at 80 00 00\n"); + } +#endif +} + +TEST_CASE("Integer32 building", "[asn1][build]") +{ + asn_error = save_g_errstr; + + const auto conv = [] (asn_len_t alen, int32_t val, const auto &buf) { + auto b = mk_asn_buf(alen); + auto s = b; + REQUIRE(asn_put_integer(&b, val) == ASN_ERR_OK); + REQUIRE(b.asn_len == (size_t)0); + check_buf(s, buf); + }; + + const auto conv_err = [] (asn_len_t alen, int32_t val, asn_err err, + std::string_view errstr) { + auto b = mk_asn_buf(alen); + g_errstr.clear(); + REQUIRE(asn_put_integer(&b, val) == err); + REQUIRE(g_errstr == errstr); + }; + + conv(3, 0x0, "x02:01:00"_cbuf); + conv(3, 0x1, "x02:01:01"_cbuf); + conv(3, 0x7f, "x02:01:7f"_cbuf); + conv(3, -0x1, "x02:01:ff"_cbuf); + conv(3, -0x80, "x02:01:80"_cbuf); + + conv(4, 0x80, "x02:02:00:80"_cbuf); + conv(4, 0xff, "x02:02:00:ff"_cbuf); + conv(4, 0x7fff, "x02:02:7f:ff"_cbuf); + conv(4, -0x81, "x02:02:ff:7f"_cbuf); + conv(4, -0xff, "x02:02:ff:01"_cbuf); + conv(4, -0x100, "x02:02:ff:00"_cbuf); + conv(4, -0x8000, "x02:02:80:00"_cbuf); + + conv(5, 0x8000, "x02:03:00:80:00"_cbuf); + conv(5, 0xffff, "x02:03:00:ff:ff"_cbuf); + conv(5, 0x7fffff, "x02:03:7f:ff:ff"_cbuf); + conv(5, -0x8001, "x02:03:ff:7f:ff"_cbuf); + conv(5, -0xffff, "x02:03:ff:00:01"_cbuf); + conv(5, -0x10000, "x02:03:ff:00:00"_cbuf); + conv(5, -0x800000, "x02:03:80:00:00"_cbuf); + + conv(6, 0x800000, "x02:04:00:80:00:00"_cbuf); + conv(6, 0xffffff, "x02:04:00:ff:ff:ff"_cbuf); + conv(6, 0x7fffffff, "x02:04:7f:ff:ff:ff"_cbuf); + conv(6, -0x800001, "x02:04:ff:7f:ff:ff"_cbuf); + conv(6, -0xffffff, "x02:04:ff:00:00:01"_cbuf); + conv(6, -0x1000000, "x02:04:ff:00:00:00"_cbuf); + conv(6, -0x80000000, "x02:04:80:00:00:00"_cbuf); + + SECTION("empty buffer") { + conv_err(0, 0, ASN_ERR_EOBUF, ""); + } + SECTION("buffer too short for length field") { + conv_err(1, 0, ASN_ERR_EOBUF, ""); + } + SECTION("buffer too short") { + conv_err(2, 0, ASN_ERR_EOBUF, ""); + conv_err(3, 0xff, ASN_ERR_EOBUF, ""); + conv_err(4, 0xffff, ASN_ERR_EOBUF, ""); + conv_err(5, 0xffffff, ASN_ERR_EOBUF, ""); + conv_err(5, 0x7fffffff, ASN_ERR_EOBUF, ""); + conv_err(2, -0x80, ASN_ERR_EOBUF, ""); + conv_err(3, -0x8000, ASN_ERR_EOBUF, ""); + conv_err(4, -0x800000, ASN_ERR_EOBUF, ""); + conv_err(5, -0x80000000, ASN_ERR_EOBUF, ""); + } +} + +TEST_CASE("Oid parsing", "[asn1][parse]") +{ + asn_error = save_g_errstr; + + /** + * Sucessfully parse a INTEGER value. + * + * \param buf buffer to parse + * \param xval expected value + */ + const auto conv = [] (const auto &buf, const asn_oid &xval) { + auto r = check_header(buf, ASN_TYPE_OBJID); + + struct asn_oid val; + REQUIRE(asn_get_objid_raw(&r.buf, r.alen, &val) == ASN_ERR_OK); + REQUIRE(asn_compare_oid(&val, &xval) == 0); + }; + + /** + * Parse INTEGER with error. + * + * \param buf buffer to parse + * \param err expected error from value parser + * \param errstr expected error string + */ + const auto conv_err = [] (const auto &buf, asn_err err, + std::string_view errstr) { + auto r = check_header(buf, ASN_TYPE_OBJID); + + g_errstr.clear(); + struct asn_oid val; + REQUIRE(asn_get_objid_raw(&r.buf, r.alen, &val) == err); + REQUIRE(g_errstr == errstr); + }; + + conv("x06:01:00"_cbuf, asn_oid {2, {0, 0}}); + conv("x06:01:28"_cbuf, asn_oid {2, {1, 0}}); + conv("x06:01:50"_cbuf, asn_oid {2, {2, 0}}); + + conv("x06:01:27"_cbuf, asn_oid {2, {0, 39}}); + conv("x06:01:4f"_cbuf, asn_oid {2, {1, 39}}); + conv("x06:01:7f"_cbuf, asn_oid {2, {2, 47}}); + + conv("x06:02:81:00"_cbuf, asn_oid {2, {2, 48}}); + conv("x06:02:ff:7f"_cbuf, asn_oid {2, {2, 16303}}); + conv("x06:03:ff:ff:7f"_cbuf, asn_oid {2, {2, 2097071}}); + conv("x06:04:ff:ff:ff:7f"_cbuf, asn_oid {2, {2, 268435375}}); + conv("x06:05:8f:ff:ff:ff:7f"_cbuf, asn_oid {2, {2, 4294967215}}); + + /* maximum OID */ + conv("x06:82:02:7b:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f"_cbuf, asn_oid {128, { + 2, 4294967215, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + }}); + + SECTION("truncated OID") { +#ifndef BOGUS_CVE_2019_5610_FIX + conv_err("x06:02:01"_cbuf, ASN_ERR_EOBUF, + "truncated OBJID at 01\n"); +#endif + conv_err("x06:01:8f"_cbuf, ASN_ERR_EOBUF, + "unterminated subid at\n"); + conv_err("x06:04:07:7f:82:8e"_cbuf, ASN_ERR_EOBUF, + "unterminated subid at\n"); + } + SECTION("short OID") { + conv_err("x06:00"_cbuf, ASN_ERR_BADLEN, + "short OBJID at\n"); + } + SECTION("too long") { + conv_err("x06:81:80:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c:7c"_cbuf, ASN_ERR_BADLEN, "OID too long (128) at 7c\n"); + } + SECTION("subid too large") { + conv_err("x06:06:20:90:82:83:84:75"_cbuf, ASN_ERR_RANGE, + "OID subid too larger at 75\n"); + } +} + +TEST_CASE("Objid building", "[asn1][build]") +{ + asn_error = save_g_errstr; + + const auto conv = [] (asn_len_t alen, const asn_oid &val, const auto &buf) { + auto b = mk_asn_buf(alen); + auto s = b; + REQUIRE(asn_put_objid(&b, &val) == ASN_ERR_OK); + REQUIRE(b.asn_len == (size_t)0); + check_buf(s, buf); + }; + + const auto conv_err = [] (asn_len_t alen, const asn_oid &val, asn_err err, + std::string_view errstr) { + auto b = mk_asn_buf(alen); + g_errstr.clear(); + REQUIRE(asn_put_objid(&b, &val) == err); + REQUIRE(g_errstr == errstr); + }; + + conv(3, asn_oid {2, {0, 0}}, "x06:01:00"_cbuf); + conv(3, asn_oid {2, {1, 0}}, "x06:01:28"_cbuf); + conv(3, asn_oid {2, {2, 0}}, "x06:01:50"_cbuf); + + conv(3, asn_oid {2, {0, 39}}, "x06:01:27"_cbuf); + conv(3, asn_oid {2, {1, 39}}, "x06:01:4f"_cbuf); + conv(3, asn_oid {2, {2, 47}}, "x06:01:7f"_cbuf); + + conv(4, asn_oid {2, {2, 48}}, "x06:02:81:00"_cbuf); + conv(4, asn_oid {2, {2, 16303}}, "x06:02:ff:7f"_cbuf); + conv(5, asn_oid {2, {2, 2097071}}, "x06:03:ff:ff:7f"_cbuf); + conv(6, asn_oid {2, {2, 268435375}}, "x06:04:ff:ff:ff:7f"_cbuf); + conv(7, asn_oid {2, {2, 4294967215}}, "x06:05:8f:ff:ff:ff:7f"_cbuf); + + SECTION("sub-id too large") { + conv_err(3, asn_oid {2, {3, 0}}, ASN_ERR_RANGE, + "oid out of range (3,0)\n"); + conv_err(3, asn_oid {2, {0, 40}}, ASN_ERR_RANGE, + "oid out of range (0,40)\n"); + conv_err(3, asn_oid {2, {1, 40}}, ASN_ERR_RANGE, + "oid out of range (1,40)\n"); + conv_err(3, asn_oid {2, {2, 4294967216}}, ASN_ERR_RANGE, + "oid out of range (2,4294967216)\n"); + } + SECTION("oid too long") { + conv_err(200, asn_oid {129, {}}, ASN_ERR_RANGE, + "oid too long 129\n"); + } + SECTION("oid too short") { + conv_err(3, asn_oid {0, {}}, ASN_ERR_RANGE, + "short oid\n"); + conv_err(3, asn_oid {1, {0}}, ASN_ERR_RANGE, + "short oid\n"); + conv_err(3, asn_oid {1, {3}}, ASN_ERR_RANGE, + "oid[0] too large (3)\n"); + } + + /* maximum OID */ + conv(5 * (128 - 1) + 4, asn_oid {128, { + 2, 4294967215, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + }}, "x06:82:02:7b:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f:8f:ff:ff:ff:7f"_cbuf); +} + +/* loop tests */ Property changes on: vendor/bsnmp/dist/tests/asn1.cc ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/bsnmp/dist/tests/catch.hpp =================================================================== --- vendor/bsnmp/dist/tests/catch.hpp (nonexistent) +++ vendor/bsnmp/dist/tests/catch.hpp (revision 359490) @@ -0,0 +1,17597 @@ +/* + * Catch v2.11.0 + * Generated: 2019-11-15 15:01:56.628356 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +// start catch.hpp + + +#define CATCH_VERSION_MAJOR 2 +#define CATCH_VERSION_MINOR 11 +#define CATCH_VERSION_PATCH 0 + +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif + +// start catch_suppress_warnings.h + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(push) +# pragma warning(disable: 161 1682) +# else // __ICC +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +# endif +#elif defined __GNUC__ + // Because REQUIREs trigger GCC's -Wparentheses, and because still + // supported version of g++ have only buggy support for _Pragmas, + // Wparentheses have to be suppressed globally. +# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details + +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic ignored "-Wpadded" +#endif +// end catch_suppress_warnings.h +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +# define CATCH_CONFIG_ALL_PARTS +#endif + +// In the impl file, we want to have access to all parts of the headers +// Can also be used to sanely support PCHs +#if defined(CATCH_CONFIG_ALL_PARTS) +# define CATCH_CONFIG_EXTERNAL_INTERFACES +# if defined(CATCH_CONFIG_DISABLE_MATCHERS) +# undef CATCH_CONFIG_DISABLE_MATCHERS +# endif +# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +# endif +#endif + +#if !defined(CATCH_CONFIG_IMPL_ONLY) +// start catch_platform.h + +#ifdef __APPLE__ +# include +# if TARGET_OS_OSX == 1 +# define CATCH_PLATFORM_MAC +# elif TARGET_OS_IPHONE == 1 +# define CATCH_PLATFORM_IPHONE +# endif + +#elif defined(linux) || defined(__linux) || defined(__linux__) +# define CATCH_PLATFORM_LINUX + +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) +# define CATCH_PLATFORM_WINDOWS +#endif + +// end catch_platform.h + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// start catch_user_interfaces.h + +namespace Catch { + unsigned int rngSeed(); +} + +// end catch_user_interfaces.h +// start catch_tag_alias_autoregistrar.h + +// start catch_common.h + +// start catch_compiler_capabilities.h + +// Detect a number of compiler features - by compiler +// The following features are defined: +// +// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? +// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? +// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? +// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +#ifdef __cplusplus + +# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) +# define CATCH_CPP14_OR_GREATER +# endif + +# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +# define CATCH_CPP17_OR_GREATER +# endif + +#endif + +#if defined(CATCH_CPP17_OR_GREATER) +# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#endif + +// We have to avoid both ICC and Clang, because they try to mask themselves +// as gcc, and we want only GCC in this block +#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) +#endif + +#if defined(__clang__) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) + +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ + _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") + +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) + +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Assume that non-Windows platforms support posix signals by default +#if !defined(CATCH_PLATFORM_WINDOWS) + #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS +#endif + +//////////////////////////////////////////////////////////////////////////////// +// We know some environments not to support full POSIX signals +#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) + #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +#endif + +#ifdef __OS400__ +# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +# define CATCH_CONFIG_COLOUR_NONE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Android somehow still does not support std::to_string +#if defined(__ANDROID__) +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Not all Windows environments support SEH properly +#if defined(__MINGW32__) +# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH +#endif + +//////////////////////////////////////////////////////////////////////////////// +// PS4 +#if defined(__ORBIS__) +# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Cygwin +#ifdef __CYGWIN__ + +// Required for some versions of Cygwin to declare gettimeofday +// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin +# define _BSD_SOURCE +// some versions of cygwin (most) do not support std::to_string. Use the libstd check. +// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 +# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ + && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) + +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING + +# endif +#endif // __CYGWIN__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#if defined(_MSC_VER) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) + +# if _MSC_VER >= 1900 // Visual Studio 2015 or newer +# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +# endif + +// Universal Windows platform does not support SEH +// Or console colours (or console at all...) +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +# define CATCH_CONFIG_COLOUR_NONE +# else +# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +# endif + +// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ +// _MSVC_TRADITIONAL == 0 means new conformant preprocessor +// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor +# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) +# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +# endif +#endif // _MSC_VER + +#if defined(_REENTRANT) || defined(_MSC_VER) +// Enable async processing, as -pthread is specified or no additional linking is required +# define CATCH_INTERNAL_CONFIG_USE_ASYNC +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// Check if we are compiled with -fno-exceptions or equivalent +#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) +# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED +#endif + +//////////////////////////////////////////////////////////////////////////////// +// DJGPP +#ifdef __DJGPP__ +# define CATCH_INTERNAL_CONFIG_NO_WCHAR +#endif // __DJGPP__ + +//////////////////////////////////////////////////////////////////////////////// +// Embarcadero C++Build +#if defined(__BORLANDC__) + #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN +#endif + +//////////////////////////////////////////////////////////////////////////////// + +// Use of __COUNTER__ is suppressed during code analysis in +// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly +// handled by it. +// Otherwise all supported compilers support COUNTER macro, +// but user still might want to turn it off +#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) + #define CATCH_INTERNAL_CONFIG_COUNTER +#endif + +//////////////////////////////////////////////////////////////////////////////// + +// RTX is a special version of Windows that is real time. +// This means that it is detected as Windows, but does not provide +// the same set of capabilities as real Windows does. +#if defined(UNDER_RTSS) || defined(RTX64_BUILD) + #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH + #define CATCH_INTERNAL_CONFIG_NO_ASYNC + #define CATCH_CONFIG_COLOUR_NONE +#endif + +#if defined(__UCLIBC__) +#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Various stdlib support checks that require __has_include +#if defined(__has_include) + // Check if string_view is available and usable + #if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW + #endif + + // Check if optional is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if byte is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_BYTE + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if variant is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # if defined(__clang__) && (__clang_major__ < 8) + // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 + // fix should be in clang 8, workaround in libstdc++ 8.2 + # include + # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # define CATCH_CONFIG_NO_CPP17_VARIANT + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__clang__) && (__clang_major__ < 8) + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) +#endif // defined(__has_include) + +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) +# define CATCH_CONFIG_COUNTER +#endif +#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) +# define CATCH_CONFIG_WINDOWS_SEH +#endif +// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. +#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) +# define CATCH_CONFIG_POSIX_SIGNALS +#endif +// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. +#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) +# define CATCH_CONFIG_WCHAR +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) +# define CATCH_CONFIG_CPP11_TO_STRING +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) +# define CATCH_CONFIG_CPP17_OPTIONAL +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) +# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) +# define CATCH_CONFIG_CPP17_STRING_VIEW +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) +# define CATCH_CONFIG_CPP17_VARIANT +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) +# define CATCH_CONFIG_CPP17_BYTE +#endif + +#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) +# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE) +# define CATCH_CONFIG_NEW_CAPTURE +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +# define CATCH_CONFIG_DISABLE_EXCEPTIONS +#endif + +#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) +# define CATCH_CONFIG_POLYFILL_ISNAN +#endif + +#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) +# define CATCH_CONFIG_USE_ASYNC +#endif + +#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) +# define CATCH_CONFIG_ANDROID_LOGWRITE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) +# define CATCH_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Even if we do not think the compiler has that warning, we still have +// to provide a macro that can be used by the code. +#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS +#endif + +#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#elif defined(__clang__) && (__clang_major__ < 5) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +#define CATCH_TRY if ((true)) +#define CATCH_CATCH_ALL if ((false)) +#define CATCH_CATCH_ANON(type) if ((false)) +#else +#define CATCH_TRY try +#define CATCH_CATCH_ALL catch (...) +#define CATCH_CATCH_ANON(type) catch (type) +#endif + +#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) +#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#endif + +// end catch_compiler_capabilities.h +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#ifdef CATCH_CONFIG_COUNTER +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#else +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#endif + +#include +#include +#include + +// We need a dummy global operator<< so we can bring it into Catch namespace later +struct Catch_global_namespace_dummy {}; +std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); + +namespace Catch { + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + + class NonCopyable { + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; + + protected: + NonCopyable(); + virtual ~NonCopyable(); + }; + + struct SourceLineInfo { + + SourceLineInfo() = delete; + SourceLineInfo( char const* _file, std::size_t _line ) noexcept + : file( _file ), + line( _line ) + {} + + SourceLineInfo( SourceLineInfo const& other ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo( SourceLineInfo&& ) noexcept = default; + SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; + + bool empty() const noexcept { return file[0] == '\0'; } + bool operator == ( SourceLineInfo const& other ) const noexcept; + bool operator < ( SourceLineInfo const& other ) const noexcept; + + char const* file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // Bring in operator<< from global namespace into Catch namespace + // This is necessary because the overload of operator<< above makes + // lookup stop at namespace Catch + using ::operator<<; + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() const; + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO \ + ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) + +// end catch_common.h +namespace Catch { + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION + +// end catch_tag_alias_autoregistrar.h +// start catch_test_registry.h + +// start catch_interfaces_testcase.h + +#include + +namespace Catch { + + class TestSpec; + + struct ITestInvoker { + virtual void invoke () const = 0; + virtual ~ITestInvoker(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; + }; + + bool isThrowSafe( TestCase const& testCase, IConfig const& config ); + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + +} + +// end catch_interfaces_testcase.h +// start catch_stringref.h + +#include +#include +#include +#include + +namespace Catch { + + /// A non-owning string class (similar to the forthcoming std::string_view) + /// Note that, because a StringRef may be a substring of another string, + /// it may not be null terminated. + class StringRef { + public: + using size_type = std::size_t; + using const_iterator = const char*; + + private: + static constexpr char const* const s_empty = ""; + + char const* m_start = s_empty; + size_type m_size = 0; + + public: // construction + constexpr StringRef() noexcept = default; + + StringRef( char const* rawChars ) noexcept; + + constexpr StringRef( char const* rawChars, size_type size ) noexcept + : m_start( rawChars ), + m_size( size ) + {} + + StringRef( std::string const& stdString ) noexcept + : m_start( stdString.c_str() ), + m_size( stdString.size() ) + {} + + explicit operator std::string() const { + return std::string(m_start, m_size); + } + + public: // operators + auto operator == ( StringRef const& other ) const noexcept -> bool; + auto operator != (StringRef const& other) const noexcept -> bool { + return !(*this == other); + } + + auto operator[] ( size_type index ) const noexcept -> char { + assert(index < m_size); + return m_start[index]; + } + + public: // named queries + constexpr auto empty() const noexcept -> bool { + return m_size == 0; + } + constexpr auto size() const noexcept -> size_type { + return m_size; + } + + // Returns the current start pointer. If the StringRef is not + // null-terminated, throws std::domain_exception + auto c_str() const -> char const*; + + public: // substrings and searches + // Returns a substring of [start, start + length). + // If start + length > size(), then the substring is [start, size()). + // If start > size(), then the substring is empty. + auto substr( size_type start, size_type length ) const noexcept -> StringRef; + + // Returns the current start pointer. May not be null-terminated. + auto data() const noexcept -> char const*; + + constexpr auto isNullTerminated() const noexcept -> bool { + return m_start[m_size] == '\0'; + } + + public: // iterators + constexpr const_iterator begin() const { return m_start; } + constexpr const_iterator end() const { return m_start + m_size; } + }; + + auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; + auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; + + constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { + return StringRef( rawChars, size ); + } +} // namespace Catch + +constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { + return Catch::StringRef( rawChars, size ); +} + +// end catch_stringref.h +// start catch_preprocessor.hpp + + +#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ +#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) + +#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ +// MSVC needs more evaluations +#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) +#else +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) +#endif + +#define CATCH_REC_END(...) +#define CATCH_REC_OUT + +#define CATCH_EMPTY() +#define CATCH_DEFER(id) id CATCH_EMPTY() + +#define CATCH_REC_GET_END2() 0, CATCH_REC_END +#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 +#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 +#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT +#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) +#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) + +#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) + +#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) + +// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, +// and passes userdata as the first parameter to each invocation, +// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) +#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) +#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ +#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ +#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) +#else +// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) +#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) +#endif + +#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ +#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) + +#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) + +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper()) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) +#else +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper())) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) +#endif + +#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ + CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) + +#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) +#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) +#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) +#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) +#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) +#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) +#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _4, _5, _6) +#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) +#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) +#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) +#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) + +#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N + +#define INTERNAL_CATCH_TYPE_GEN\ + template struct TypeList {};\ + template\ + constexpr auto get_wrapper() noexcept -> TypeList { return {}; }\ + template class...> struct TemplateTypeList{};\ + template class...Cs>\ + constexpr auto get_wrapper() noexcept -> TemplateTypeList { return {}; }\ + template\ + struct append;\ + template\ + struct rewrap;\ + template class, typename...>\ + struct create;\ + template class, typename>\ + struct convert;\ + \ + template \ + struct append { using type = T; };\ + template< template class L1, typename...E1, template class L2, typename...E2, typename...Rest>\ + struct append, L2, Rest...> { using type = typename append, Rest...>::type; };\ + template< template class L1, typename...E1, typename...Rest>\ + struct append, TypeList, Rest...> { using type = L1; };\ + \ + template< template class Container, template class List, typename...elems>\ + struct rewrap, List> { using type = TypeList>; };\ + template< template class Container, template class List, class...Elems, typename...Elements>\ + struct rewrap, List, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\ + \ + template